From 0000b35288f7f7d929dd9afe7a5f4b47305f8bff Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Nov 2023 03:27:41 +0000 Subject: [PATCH 1/5] Document DefiningAnchor a bit more --- compiler/rustc_middle/src/traits/mod.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 6cd75e0872763..8af4f57d5e83a 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -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, } From 273dc22b04411b9c156375d15ad2c8cead2e619e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Nov 2023 23:35:20 +0000 Subject: [PATCH 2/5] Don't ICE when ambiguity is found when selecting Index implementation in typeck --- compiler/rustc_hir_typeck/src/expr.rs | 22 +++++++++++--- .../bad-index-modulo-higher-ranked-regions.rs | 29 +++++++++++++++++++ ...-index-modulo-higher-ranked-regions.stderr | 9 ++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs create mode 100644 tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d9b27fc13182c..8fcbe90e91a8c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3064,7 +3064,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 = @@ -3074,7 +3076,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 @@ -3110,11 +3112,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, )) diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs new file mode 100644 index 0000000000000..c8f6db7aef3e5 --- /dev/null +++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs @@ -0,0 +1,29 @@ +// Test against ICE in #118111 + +use std::ops::Index; + +struct Map { + f: F, + inner: T, +} + +impl Index for Map +where + T: Index, + 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| ...` +} diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr new file mode 100644 index 0000000000000..7c97843083916 --- /dev/null +++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr @@ -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`. From 018b85986d67945d50ea7aac176307877aaa053a Mon Sep 17 00:00:00 2001 From: ouz-a Date: Thu, 16 Nov 2023 16:04:26 +0300 Subject: [PATCH 3/5] Add VarDebugInfo to Stable MIR --- compiler/rustc_smir/src/rustc_smir/mod.rs | 45 +++++++++++++++++++- compiler/stable_mir/src/mir/body.rs | 50 +++++++++++++++++++++-- compiler/stable_mir/src/mir/visit.rs | 26 +++++++++++- 3 files changed, 116 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 167a01ab7990c..e83e301d83bf4 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -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, @@ -444,10 +447,50 @@ 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: stable_mir::mir::SourceInfo { + span: self.source_info.span.stable(tables), + scope: self.source_info.scope.into(), + }, + composite: { + if let Some(composite) = &self.composite { + Some(VarDebugInfoFragment { + ty: composite.ty.stable(tables), + projection: composite.projection.iter().map(|e| e.stable(tables)).collect(), + }) + } else { + None + } + }, + value: { + match self.value { + 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) + } + } + }, + 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 { diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index ac07246dfd3eb..8d237fc9f1d95 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -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. @@ -19,6 +19,9 @@ 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, } impl Body { @@ -26,14 +29,19 @@ impl 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, locals: LocalDecls, arg_count: usize) -> Self { + pub fn new( + blocks: Vec, + locals: LocalDecls, + arg_count: usize, + var_debug_info: Vec, + ) -> 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. @@ -427,6 +435,42 @@ pub struct Place { pub projection: Vec, } +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct VarDebugInfo { + pub name: Symbol, + pub source_info: SourceInfo, + pub composite: Option, + pub value: VarDebugInfoContents, + pub argument_index: Option, +} + +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, +} + +#[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, + 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) and user-provided type annotations (for which the projection elements diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 40bedd67352f7..488363d6a7f1e 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -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); @@ -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) { @@ -382,6 +390,22 @@ pub trait MirVisitor { let _ = args; } + fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) { + self.visit_span(&var_debug_info.source_info.span); + let location = Location(var_debug_info.source_info.span); + if let Some(composite) = &var_debug_info.composite { + self.visit_ty(&composite.ty, location); + } + match &var_debug_info.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 } => { From d0dd19a6c959c90eb7b28c3fa7f127b92fd0af36 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 17 Nov 2023 23:41:34 +0300 Subject: [PATCH 4/5] de-structure variable and add stables --- compiler/rustc_smir/src/rustc_smir/mod.rs | 68 +++++++++++++---------- compiler/stable_mir/src/mir/visit.rs | 10 ++-- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index e83e301d83bf4..04986a6c02fbe 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -457,35 +457,9 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { stable_mir::mir::VarDebugInfo { name: self.name.to_string(), - source_info: stable_mir::mir::SourceInfo { - span: self.source_info.span.stable(tables), - scope: self.source_info.scope.into(), - }, - composite: { - if let Some(composite) = &self.composite { - Some(VarDebugInfoFragment { - ty: composite.ty.stable(tables), - projection: composite.projection.iter().map(|e| e.stable(tables)).collect(), - }) - } else { - None - } - }, - value: { - match self.value { - 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) - } - } - }, + 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, } } @@ -498,6 +472,42 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { } } +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 { diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 488363d6a7f1e..d90808725ae40 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -391,12 +391,14 @@ pub trait MirVisitor { } fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) { - self.visit_span(&var_debug_info.source_info.span); - let location = Location(var_debug_info.source_info.span); - if let Some(composite) = &var_debug_info.composite { + 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 &var_debug_info.value { + match value { VarDebugInfoContents::Place(place) => { self.visit_place(place, PlaceContext::NON_USE, location); } From 0b25415559662352bbfd03a315d2a715663618b6 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Tue, 21 Nov 2023 16:56:19 +0300 Subject: [PATCH 5/5] remove quotation from filename --- compiler/rustc_smir/src/rustc_smir/mod.rs | 16 +++++++--------- compiler/stable_mir/src/lib.rs | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 167a01ab7990c..0201df721f294 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -69,15 +69,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 { diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 91f1066d7205a..5eb6a8a5e543e 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -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)]