Skip to content

Commit

Permalink
Auto merge of rust-lang#118141 - matthiaskrgr:rollup-djkmfwt, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 4 pull requests

Successful merges:

 - rust-lang#117972 (Add VarDebugInfo to Stable MIR)
 - rust-lang#118110 (Document `DefiningAnchor` a bit more)
 - rust-lang#118112 (Don't ICE when ambiguity is found when selecting `Index` implementation in typeck)
 - rust-lang#118135 (Remove quotation from filename in stable_mir)

Failed merges:

 - rust-lang#118012 (Add support for global allocation in smir)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Nov 21, 2023
2 parents 2f8d81f + a687126 commit 40ae0b8
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 23 deletions.
22 changes: 18 additions & 4 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3067,7 +3067,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
};

self.commit_if_ok(|_| {
self.commit_if_ok(|snapshot| {
let outer_universe = self.universe();

let ocx = ObligationCtxt::new(self);
let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
let impl_trait_ref =
Expand All @@ -3077,7 +3079,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Match the impl self type against the base ty. If this fails,
// we just skip this impl, since it's not particularly useful.
let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
ocx.eq(&cause, self.param_env, base_ty, impl_trait_ref.self_ty())?;

// Register the impl's predicates. One of these predicates
// must be unsatisfied, or else we wouldn't have gotten here
Expand Down Expand Up @@ -3113,11 +3115,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
);

let errors = ocx.select_where_possible();
let true_errors = ocx.select_where_possible();

// Do a leak check -- we can't really report report a useful error here,
// but it at least avoids an ICE when the error has to do with higher-ranked
// lifetimes.
self.leak_check(outer_universe, Some(snapshot))?;

// Bail if we have ambiguity errors, which we can't report in a useful way.
let ambiguity_errors = ocx.select_all_or_error();
if true_errors.is_empty() && !ambiguity_errors.is_empty() {
return Err(NoSolution);
}

// There should be at least one error reported. If not, we
// will still delay a span bug in `report_fulfillment_errors`.
Ok::<_, NoSolution>((
self.err_ctxt().report_fulfillment_errors(errors),
self.err_ctxt().report_fulfillment_errors(true_errors),
impl_trait_ref.args.type_at(1),
element_ty,
))
Expand Down
21 changes: 17 additions & 4 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,13 +956,26 @@ pub enum CodegenObligationError {
FulfillmentError,
}

/// Defines the treatment of opaque types in a given inference context.
///
/// This affects both what opaques are allowed to be defined, but also whether
/// opaques are replaced with inference vars eagerly in the old solver (e.g.
/// in projection, and in the signature during function type-checking).
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum DefiningAnchor {
/// `DefId` of the item.
/// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly
/// replace opaque types in `replace_opaque_types_with_inference_vars`.
Bind(LocalDefId),
/// When opaque types are not resolved, we `Bubble` up, meaning
/// return the opaque/hidden type pair from query, for caller of query to handle it.
/// In contexts where we don't currently know what opaques are allowed to be
/// defined, such as (old solver) canonical queries, we will simply allow
/// opaques to be defined, but "bubble" them up in the canonical response or
/// otherwise treat them to be handled later.
///
/// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
/// which may affect what predicates pass and fail in the old trait solver.
Bubble,
/// Used to catch type mismatch errors when handling opaque types.
/// Do not allow any opaques to be defined. This is used to catch type mismatch
/// errors when handling opaque types, and also should be used when we would
/// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
Error,
}
71 changes: 61 additions & 10 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use rustc_middle::ty::{self, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, Variance
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_target::abi::FieldIdx;
use stable_mir::mir::mono::InstanceDef;
use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
use stable_mir::mir::{
Body, ConstOperand, CopyNonOverlapping, Statement, UserTypeProjection, VarDebugInfoFragment,
VariantIdx,
};
use stable_mir::ty::{
AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
Expand Down Expand Up @@ -69,15 +72,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {

fn get_filename(&self, span: &Span) -> Filename {
let tables = self.0.borrow();
opaque(
&tables
.tcx
.sess
.source_map()
.span_to_filename(tables[*span])
.display(rustc_span::FileNameDisplayPreference::Local)
.to_string(),
)
tables
.tcx
.sess
.source_map()
.span_to_filename(tables[*span])
.display(rustc_span::FileNameDisplayPreference::Local)
.to_string()
}

fn get_lines(&self, span: &Span) -> LineInfo {
Expand Down Expand Up @@ -444,17 +445,67 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
})
.collect(),
self.arg_count,
self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
)
}
}

impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
type T = stable_mir::mir::VarDebugInfo;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
stable_mir::mir::VarDebugInfo {
name: self.name.to_string(),
source_info: self.source_info.stable(tables),
composite: self.composite.as_ref().map(|composite| composite.stable(tables)),
value: self.value.stable(tables),
argument_index: self.argument_index,
}
}
}

impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
type T = stable_mir::mir::Statement;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
}
}

impl<'tcx> Stable<'tcx> for mir::SourceInfo {
type T = stable_mir::mir::SourceInfo;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
}
}

impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
type T = stable_mir::mir::VarDebugInfoFragment;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
VarDebugInfoFragment {
ty: self.ty.stable(tables),
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
}
}
}

impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
type T = stable_mir::mir::VarDebugInfoContents;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
match self {
mir::VarDebugInfoContents::Place(place) => {
stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
}
mir::VarDebugInfoContents::Const(const_operand) => {
let op = ConstOperand {
span: const_operand.span.stable(tables),
user_ty: const_operand.user_ty.map(|index| index.as_usize()),
const_: const_operand.const_.stable(tables),
};
stable_mir::mir::VarDebugInfoContents::Const(op)
}
}
}
}

impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
type T = stable_mir::mir::StatementKind;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
Expand Down
2 changes: 1 addition & 1 deletion compiler/stable_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub enum ItemKind {
Const,
}

pub type Filename = Opaque;
pub type Filename = String;

/// Holds information about an item in the crate.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
Expand Down
50 changes: 47 additions & 3 deletions compiler/stable_mir/src/mir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::mir::pretty::{function_body, pretty_statement};
use crate::ty::{
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
};
use crate::{Error, Opaque, Span};
use crate::{Error, Opaque, Span, Symbol};
use std::io;

/// The SMIR representation of a single function.
Expand All @@ -19,21 +19,29 @@ pub struct Body {

// The number of arguments this function takes.
pub(super) arg_count: usize,

// Debug information pertaining to user variables, including captures.
pub(super) var_debug_info: Vec<VarDebugInfo>,
}

impl Body {
/// Constructs a `Body`.
///
/// A constructor is required to build a `Body` from outside the crate
/// because the `arg_count` and `locals` fields are private.
pub fn new(blocks: Vec<BasicBlock>, locals: LocalDecls, arg_count: usize) -> Self {
pub fn new(
blocks: Vec<BasicBlock>,
locals: LocalDecls,
arg_count: usize,
var_debug_info: Vec<VarDebugInfo>,
) -> Self {
// If locals doesn't contain enough entries, it can lead to panics in
// `ret_local`, `arg_locals`, and `inner_locals`.
assert!(
locals.len() > arg_count,
"A Body must contain at least a local for the return value and each of the function's arguments"
);
Self { blocks, locals, arg_count }
Self { blocks, locals, arg_count, var_debug_info }
}

/// Return local that holds this function's return value.
Expand Down Expand Up @@ -427,6 +435,42 @@ pub struct Place {
pub projection: Vec<ProjectionElem>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VarDebugInfo {
pub name: Symbol,
pub source_info: SourceInfo,
pub composite: Option<VarDebugInfoFragment>,
pub value: VarDebugInfoContents,
pub argument_index: Option<u16>,
}

pub type SourceScope = u32;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SourceInfo {
pub span: Span,
pub scope: SourceScope,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VarDebugInfoFragment {
pub ty: Ty,
pub projection: Vec<ProjectionElem>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VarDebugInfoContents {
Place(Place),
Const(ConstOperand),
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ConstOperand {
pub span: Span,
pub user_ty: Option<UserTypeAnnotationIndex>,
pub const_: Const,
}

// In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This
// is so it can be used for both Places (for which the projection elements are of type
// ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
Expand Down
28 changes: 27 additions & 1 deletion compiler/stable_mir/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,12 @@ pub trait MirVisitor {
self.super_assert_msg(msg, location)
}

fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
self.super_var_debug_info(var_debug_info);
}

fn super_body(&mut self, body: &Body) {
let Body { blocks, locals: _, arg_count } = body;
let Body { blocks, locals: _, arg_count, var_debug_info } = body;

for bb in blocks {
self.visit_basic_block(bb);
Expand All @@ -145,6 +149,10 @@ pub trait MirVisitor {
for (idx, arg) in body.inner_locals().iter().enumerate() {
self.visit_local_decl(idx + local_start, arg)
}

for info in var_debug_info.iter() {
self.visit_var_debug_info(info);
}
}

fn super_basic_block(&mut self, bb: &BasicBlock) {
Expand Down Expand Up @@ -382,6 +390,24 @@ pub trait MirVisitor {
let _ = args;
}

fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } =
var_debug_info;
self.visit_span(&source_info.span);
let location = Location(source_info.span);
if let Some(composite) = composite {
self.visit_ty(&composite.ty, location);
}
match value {
VarDebugInfoContents::Place(place) => {
self.visit_place(place, PlaceContext::NON_USE, location);
}
VarDebugInfoContents::Const(constant) => {
self.visit_const(&constant.const_, location);
}
}
}

fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) {
match msg {
AssertMessage::BoundsCheck { len, index } => {
Expand Down
29 changes: 29 additions & 0 deletions tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Test against ICE in #118111

use std::ops::Index;

struct Map<T, F> {
f: F,
inner: T,
}

impl<T, F, Idx> Index<Idx> for Map<T, F>
where
T: Index<Idx>,
F: FnOnce(&T, Idx) -> Idx,
{
type Output = T::Output;

fn index(&self, index: Idx) -> &Self::Output {
todo!()
}
}

fn main() {
Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0];
//~^ ERROR cannot index into a value of type
// Problem here is that
// `f: |_, i: usize| ...`
// should be
// `f: |_: &_, i: usize| ...`
}
9 changes: 9 additions & 0 deletions tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0608]: cannot index into a value of type `Map<[usize; 1], {closure@$DIR/bad-index-modulo-higher-ranked-regions.rs:23:32: 23:45}>`
--> $DIR/bad-index-modulo-higher-ranked-regions.rs:23:55
|
LL | Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0];
| ^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0608`.

0 comments on commit 40ae0b8

Please sign in to comment.