diff options
Diffstat (limited to 'compiler')
130 files changed, 1586 insertions, 1249 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index fb012d9802f..b3bac1d7ecd 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1861,6 +1861,10 @@ pub enum TyKind { Never, /// A tuple (`(A, B, C, D,...)`). Tup(Vec<P<Ty>>), + /// An anonymous struct type i.e. `struct { foo: Type }` + AnonymousStruct(Vec<FieldDef>, bool), + /// An anonymous union type i.e. `union { bar: Type }` + AnonymousUnion(Vec<FieldDef>, bool), /// A path (`module::module::...::Type`), optionally /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`. /// diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 374a6ec972f..071d41ea2b2 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -484,6 +484,9 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { visit_vec(bounds, |bound| vis.visit_param_bound(bound)); } TyKind::MacCall(mac) => vis.visit_mac_call(mac), + TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => { + fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); + } } vis.visit_span(span); visit_lazy_tts(tokens, vis); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c50b334d3e9..f1a99bc51c9 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -404,6 +404,9 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac), + TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => { + walk_list!(visitor, visit_field_def, fields) + } TyKind::Never | TyKind::CVarArgs => {} } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 483135ed3a3..866f2180bb6 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -560,8 +560,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } - /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`, - /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }` + /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`, + /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }` /// and save the block id to use it as a break target for desugaring of the `?` operator. fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> { self.with_catch_scope(body.id, |this| { @@ -590,9 +590,9 @@ impl<'hir> LoweringContext<'_, 'hir> { let ok_wrapped_span = this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); - // `::std::ops::Try::from_ok($tail_expr)` + // `::std::ops::Try::from_output($tail_expr)` block.expr = Some(this.wrap_in_try_constructor( - hir::LangItem::TryFromOk, + hir::LangItem::TryTraitFromOutput, try_span, tail_expr, ok_wrapped_span, @@ -1579,14 +1579,14 @@ impl<'hir> LoweringContext<'_, 'hir> { self.allow_try_trait.clone(), ); - // `Try::into_result(<expr>)` + // `Try::branch(<expr>)` let scrutinee = { // expand <expr> let sub_expr = self.lower_expr_mut(sub_expr); self.expr_call_lang_item_fn( unstable_span, - hir::LangItem::TryIntoResult, + hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], ) }; @@ -1604,8 +1604,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let attrs = vec![attr]; - // `Ok(val) => #[allow(unreachable_code)] val,` - let ok_arm = { + // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,` + let continue_arm = { let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); let val_expr = self.arena.alloc(self.expr_ident_with_attrs( @@ -1614,27 +1614,21 @@ impl<'hir> LoweringContext<'_, 'hir> { val_pat_nid, ThinVec::from(attrs.clone()), )); - let ok_pat = self.pat_ok(span, val_pat); - self.arm(ok_pat, val_expr) + let continue_pat = self.pat_cf_continue(unstable_span, val_pat); + self.arm(continue_pat, val_expr) }; - // `Err(err) => #[allow(unreachable_code)] - // return Try::from_error(From::from(err)),` - let err_arm = { - let err_ident = Ident::with_dummy_span(sym::err); - let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); - let from_expr = { - let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid); - self.expr_call_lang_item_fn( - try_span, - hir::LangItem::FromFrom, - arena_vec![self; err_expr], - ) - }; - let from_err_expr = self.wrap_in_try_constructor( - hir::LangItem::TryFromError, - unstable_span, - from_expr, + // `ControlFlow::Break(residual) => + // #[allow(unreachable_code)] + // return Try::from_residual(residual),` + let break_arm = { + let residual_ident = Ident::with_dummy_span(sym::residual); + let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident); + let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid); + let from_residual_expr = self.wrap_in_try_constructor( + hir::LangItem::TryTraitFromResidual, + try_span, + self.arena.alloc(residual_expr), unstable_span, ); let thin_attrs = ThinVec::from(attrs); @@ -1645,25 +1639,25 @@ impl<'hir> LoweringContext<'_, 'hir> { try_span, hir::ExprKind::Break( hir::Destination { label: None, target_id }, - Some(from_err_expr), + Some(from_residual_expr), ), thin_attrs, )) } else { self.arena.alloc(self.expr( try_span, - hir::ExprKind::Ret(Some(from_err_expr)), + hir::ExprKind::Ret(Some(from_residual_expr)), thin_attrs, )) }; - let err_pat = self.pat_err(try_span, err_local); - self.arm(err_pat, ret_expr) + let break_pat = self.pat_cf_break(try_span, residual_local); + self.arm(break_pat, ret_expr) }; hir::ExprKind::Match( scrutinee, - arena_vec![self; err_arm, ok_arm], + arena_vec![self; break_arm, continue_arm], hir::MatchSource::TryDesugar, ) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index aa236a690ec..292643d6d75 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -789,7 +789,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> { + pub(super) fn lower_field_def( + &mut self, + (index, f): (usize, &FieldDef), + ) -> hir::FieldDef<'hir> { let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind { let t = self.lower_path_ty( &f.ty, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0439de0ee7b..56f97054f96 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -332,7 +332,7 @@ pub fn lower_crate<'a, 'hir>( lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), - allow_try_trait: Some([sym::try_trait][..].into()), + allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), } .lower_crate(krate) @@ -1267,6 +1267,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, + // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS + TyKind::AnonymousStruct(ref _fields, _recovered) => { + self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit(); + hir::TyKind::Err + } + TyKind::AnonymousUnion(ref _fields, _recovered) => { + self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit(); + hir::TyKind::Err + } TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Rptr(ref region, ref mt) => { @@ -2481,14 +2490,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.pat(span, hir::PatKind::Lit(expr)) } - fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { + fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) } - fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { + fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 6d6438920c0..ba2da769497 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -175,10 +175,30 @@ impl<'a> AstValidator<'a> { } } } + TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => { + self.with_banned_assoc_ty_bound(|this| { + walk_list!(this, visit_struct_field_def, fields) + }); + } _ => visit::walk_ty(self, t), } } + fn visit_struct_field_def(&mut self, field: &'a FieldDef) { + if let Some(ident) = field.ident { + if ident.name == kw::Underscore { + self.check_anonymous_field(field); + self.visit_vis(&field.vis); + self.visit_ident(ident); + self.visit_ty_common(&field.ty); + self.walk_ty(&field.ty); + walk_list!(self, visit_attribute, &field.attrs); + return; + } + } + self.visit_field_def(field); + } + fn err_handler(&self) -> &rustc_errors::Handler { &self.session.diagnostic() } @@ -213,6 +233,66 @@ impl<'a> AstValidator<'a> { err.emit(); } + fn check_anonymous_field(&self, field: &FieldDef) { + let FieldDef { ty, .. } = field; + match &ty.kind { + TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => { + // We already checked for `kw::Underscore` before calling this function, + // so skip the check + } + TyKind::Path(..) => { + // If the anonymous field contains a Path as type, we can't determine + // if the path is a valid struct or union, so skip the check + } + _ => { + let msg = "unnamed fields can only have struct or union types"; + let label = "not a struct or union"; + self.err_handler() + .struct_span_err(field.span, msg) + .span_label(ty.span, label) + .emit(); + } + } + } + + fn deny_anonymous_struct(&self, ty: &Ty) { + match &ty.kind { + TyKind::AnonymousStruct(..) => { + self.err_handler() + .struct_span_err( + ty.span, + "anonymous structs are not allowed outside of unnamed struct or union fields", + ) + .span_label(ty.span, "anonymous struct declared here") + .emit(); + } + TyKind::AnonymousUnion(..) => { + self.err_handler() + .struct_span_err( + ty.span, + "anonymous unions are not allowed outside of unnamed struct or union fields", + ) + .span_label(ty.span, "anonymous union declared here") + .emit(); + } + _ => {} + } + } + + fn deny_anonymous_field(&self, field: &FieldDef) { + if let Some(ident) = field.ident { + if ident.name == kw::Underscore { + self.err_handler() + .struct_span_err( + field.span, + "anonymous fields are not allowed outside of structs or unions", + ) + .span_label(ident.span, "anonymous field declared here") + .emit() + } + } + } + fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { @@ -732,6 +812,71 @@ impl<'a> AstValidator<'a> { ) .emit(); } + + fn visit_ty_common(&mut self, ty: &'a Ty) { + match ty.kind { + TyKind::BareFn(ref bfty) => { + self.check_fn_decl(&bfty.decl, SelfSemantic::No); + Self::check_decl_no_pat(&bfty.decl, |span, _, _| { + struct_span_err!( + self.session, + span, + E0561, + "patterns aren't allowed in function pointer types" + ) + .emit(); + }); + self.check_late_bound_lifetime_defs(&bfty.generic_params); + } + TyKind::TraitObject(ref bounds, ..) => { + let mut any_lifetime_bounds = false; + for bound in bounds { + if let GenericBound::Outlives(ref lifetime) = *bound { + if any_lifetime_bounds { + struct_span_err!( + self.session, + lifetime.ident.span, + E0226, + "only a single explicit lifetime bound is permitted" + ) + .emit(); + break; + } + any_lifetime_bounds = true; + } + } + self.no_questions_in_bounds(bounds, "trait object types", false); + } + TyKind::ImplTrait(_, ref bounds) => { + if self.is_impl_trait_banned { + struct_span_err!( + self.session, + ty.span, + E0667, + "`impl Trait` is not allowed in path parameters" + ) + .emit(); + } + + if let Some(outer_impl_trait_sp) = self.outer_impl_trait { + struct_span_err!( + self.session, + ty.span, + E0666, + "nested `impl Trait` is not allowed" + ) + .span_label(outer_impl_trait_sp, "outer `impl Trait`") + .span_label(ty.span, "nested `impl Trait` here") + .emit(); + } + + if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) { + self.err_handler().span_err(ty.span, "at least one trait must be specified"); + } + } + _ => {} + } + } } /// Checks that generic parameters are in the correct order, @@ -850,72 +995,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_ty(&mut self, ty: &'a Ty) { - match ty.kind { - TyKind::BareFn(ref bfty) => { - self.check_fn_decl(&bfty.decl, SelfSemantic::No); - Self::check_decl_no_pat(&bfty.decl, |span, _, _| { - struct_span_err!( - self.session, - span, - E0561, - "patterns aren't allowed in function pointer types" - ) - .emit(); - }); - self.check_late_bound_lifetime_defs(&bfty.generic_params); - } - TyKind::TraitObject(ref bounds, ..) => { - let mut any_lifetime_bounds = false; - for bound in bounds { - if let GenericBound::Outlives(ref lifetime) = *bound { - if any_lifetime_bounds { - struct_span_err!( - self.session, - lifetime.ident.span, - E0226, - "only a single explicit lifetime bound is permitted" - ) - .emit(); - break; - } - any_lifetime_bounds = true; - } - } - self.no_questions_in_bounds(bounds, "trait object types", false); - } - TyKind::ImplTrait(_, ref bounds) => { - if self.is_impl_trait_banned { - struct_span_err!( - self.session, - ty.span, - E0667, - "`impl Trait` is not allowed in path parameters" - ) - .emit(); - } - - if let Some(outer_impl_trait_sp) = self.outer_impl_trait { - struct_span_err!( - self.session, - ty.span, - E0666, - "nested `impl Trait` is not allowed" - ) - .span_label(outer_impl_trait_sp, "outer `impl Trait`") - .span_label(ty.span, "nested `impl Trait` here") - .emit(); - } - - if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) { - self.err_handler().span_err(ty.span, "at least one trait must be specified"); - } - - self.walk_ty(ty); - return; - } - _ => {} - } - + self.visit_ty_common(ty); + self.deny_anonymous_struct(ty); self.walk_ty(ty) } @@ -929,6 +1010,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_lifetime(self, lifetime); } + fn visit_field_def(&mut self, s: &'a FieldDef) { + self.deny_anonymous_field(s); + visit::walk_field_def(self, s) + } + fn visit_item(&mut self, item: &'a Item) { if item.attrs.iter().any(|attr| self.session.is_proc_macro_attr(attr)) { self.has_proc_macro_decls = true; @@ -1084,14 +1170,42 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_mod_file_item_asciionly(item.ident); } } - ItemKind::Union(ref vdata, _) => { - if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata { - self.err_handler() - .span_err(item.span, "tuple and unit unions are not permitted"); + ItemKind::Struct(ref vdata, ref generics) => match vdata { + // Duplicating the `Visitor` logic allows catching all cases + // of `Anonymous(Struct, Union)` outside of a field struct or union. + // + // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it + // encounters, and only on `ItemKind::Struct` and `ItemKind::Union` + // it uses `visit_ty_common`, which doesn't contain that specific check. + VariantData::Struct(ref fields, ..) => { + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.visit_generics(generics); + self.with_banned_assoc_ty_bound(|this| { + walk_list!(this, visit_struct_field_def, fields); + }); + walk_list!(self, visit_attribute, &item.attrs); + return; } + _ => {} + }, + ItemKind::Union(ref vdata, ref generics) => { if vdata.fields().is_empty() { self.err_handler().span_err(item.span, "unions cannot have zero fields"); } + match vdata { + VariantData::Struct(ref fields, ..) => { + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.visit_generics(generics); + self.with_banned_assoc_ty_bound(|this| { + walk_list!(this, visit_struct_field_def, fields); + }); + walk_list!(self, visit_attribute, &item.attrs); + return; + } + _ => {} + } } ItemKind::Const(def, .., None) => { self.check_defaultness(item.span, def); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index dc3383dae84..4996c2195ef 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -713,10 +713,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); gate_all!( - extended_key_value_attributes, - "arbitrary expressions in key-value attributes are unstable" - ); - gate_all!( const_generics_defaults, "default values for const generic parameters are experimental" ); @@ -725,6 +721,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { // involved, so we only emit errors where there are no other parsing errors. gate_all!(destructuring_assignment, "destructuring assignments are unstable"); } + gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 0e42e0e3793..da9d89745a8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -140,12 +140,15 @@ pub fn print_crate<'a>( // and also addresses some specific regressions described in #63896 and #73345. fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { if let TokenTree::Token(token) = prev { + if matches!(token.kind, token::Dot) { + return false; + } if let token::DocComment(comment_kind, ..) = token.kind { return comment_kind != CommentKind::Line; } } match tt { - TokenTree::Token(token) => token.kind != token::Comma, + TokenTree::Token(token) => !matches!(token.kind, token::Comma | token::Not | token::Dot), TokenTree::Delimited(_, DelimToken::Paren, _) => { !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. })) } @@ -951,6 +954,14 @@ impl<'a> State<'a> { } self.pclose(); } + ast::TyKind::AnonymousStruct(ref fields, ..) => { + self.s.word("struct"); + self.print_record_struct_body(fields, ty.span); + } + ast::TyKind::AnonymousUnion(ref fields, ..) => { + self.s.word("union"); + self.print_record_struct_body(fields, ty.span); + } ast::TyKind::Paren(ref typ) => { self.popen(); self.print_type(typ); @@ -1386,6 +1397,29 @@ impl<'a> State<'a> { } } + crate fn print_record_struct_body( + &mut self, + fields: &Vec<ast::FieldDef>, + span: rustc_span::Span, + ) { + self.nbsp(); + self.bopen(); + self.hardbreak_if_not_bol(); + + for field in fields { + self.hardbreak_if_not_bol(); + self.maybe_print_comment(field.span.lo()); + self.print_outer_attributes(&field.attrs); + self.print_visibility(&field.vis); + self.print_ident(field.ident.unwrap()); + self.word_nbsp(":"); + self.print_type(&field.ty); + self.s.word(","); + } + + self.bclose(span) + } + crate fn print_struct( &mut self, struct_def: &ast::VariantData, @@ -1415,24 +1449,9 @@ impl<'a> State<'a> { self.end(); self.end(); // Close the outer-box. } - ast::VariantData::Struct(..) => { + ast::VariantData::Struct(ref fields, ..) => { self.print_where_clause(&generics.where_clause); - self.nbsp(); - self.bopen(); - self.hardbreak_if_not_bol(); - - for field in struct_def.fields() { - self.hardbreak_if_not_bol(); - self.maybe_print_comment(field.span.lo()); - self.print_outer_attributes(&field.attrs); - self.print_visibility(&field.vis); - self.print_ident(field.ident.unwrap()); - self.word_nbsp(":"); - self.print_type(&field.ty); - self.s.word(","); - } - - self.bclose(span) + self.print_record_struct_body(fields, span); } } } diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index a09e3257786..357a9f2daf7 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -13,7 +13,7 @@ pub(crate) fn codegen( module: &mut impl Module, unwind_context: &mut UnwindContext, ) -> bool { - let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE).iter().any(|(_, list)| { + let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| { use rustc_middle::middle::dependency_format::Linkage; list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 004e6bddaf3..24d933728db 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -42,7 +42,7 @@ fn emit_module( unwind_context.emit(&mut product); - let tmp_file = tcx.output_filenames(LOCAL_CRATE).temp_path(OutputType::Object, Some(&name)); + let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); let obj = product.object.write().unwrap(); if let Err(err) = std::fs::write(&tmp_file, obj) { tcx.sess.fatal(&format!("error writing object file: {}", err)); @@ -74,7 +74,7 @@ fn reuse_workproduct_for_cgu( let work_product = cgu.work_product(tcx); if let Some(saved_file) = &work_product.saved_file { let obj_out = tcx - .output_filenames(LOCAL_CRATE) + .output_filenames(()) .temp_path(OutputType::Object, Some(&cgu.name().as_str())); object = Some(obj_out.clone()); let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, &saved_file); @@ -190,7 +190,7 @@ pub(crate) fn run_aot( let mut work_products = FxHashMap::default(); let cgus = if tcx.sess.opts.output_types.should_codegen() { - tcx.collect_and_partition_mono_items(LOCAL_CRATE).1 + tcx.collect_and_partition_mono_items(()).1 } else { // If only `--emit metadata` is used, we shouldn't perform any codegen. // Also `tcx.collect_and_partition_mono_items` may panic in that case. @@ -276,7 +276,7 @@ pub(crate) fn run_aot( .to_string(); let tmp_file = tcx - .output_filenames(LOCAL_CRATE) + .output_filenames(()) .temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| { @@ -353,7 +353,7 @@ fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { .join("\n"); let output_object_file = - tcx.output_filenames(LOCAL_CRATE).temp_path(OutputType::Object, Some(cgu_name)); + tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); // Assemble `global_asm` let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 53c93f6a9dd..632e86da736 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -8,7 +8,6 @@ use std::os::raw::{c_char, c_int}; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; -use rustc_session::config::EntryFnType; use cranelift_jit::{JITBuilder, JITModule}; @@ -66,7 +65,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { matches!(backend_config.codegen_mode, CodegenMode::JitLazy), ); - let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); + let (_, cgus) = tcx.collect_and_partition_mono_items(()); let mono_items = cgus .iter() .map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter()) @@ -179,7 +178,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> { let mut dylib_paths = Vec::new(); let crate_info = CrateInfo::new(tcx); - let formats = tcx.dependency_formats(LOCAL_CRATE); + let formats = tcx.dependency_formats(()); let data = &formats .iter() .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index d504024a335..d1958c5f96b 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -15,7 +15,7 @@ pub(crate) fn maybe_create_entry_wrapper( unwind_context: &mut UnwindContext, is_jit: bool, ) { - let (main_def_id, is_main_fn) = match tcx.entry_fn(LOCAL_CRATE) { + let (main_def_id, is_main_fn) = match tcx.entry_fn(()) { Some((def_id, entry_ty)) => ( def_id, match entry_ty { diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index 158811c5eaf..cd8c5b51608 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -214,7 +214,7 @@ pub(crate) fn write_ir_file( return; } - let clif_output_dir = tcx.output_filenames(LOCAL_CRATE).with_extension("clif"); + let clif_output_dir = tcx.output_filenames(()).with_extension("clif"); match std::fs::create_dir(&clif_output_dir) { Ok(()) => {} diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index a571418c1f5..0aef77129d8 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -283,7 +283,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {} InlineAsmArch::Nvptx64 => {} - InlineAsmArch::PowerPC => {} + InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} InlineAsmArch::SpirV => {} diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 4219797c5cd..5b4a187a1d5 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -20,7 +20,6 @@ use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; -use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath}; @@ -92,13 +91,12 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm: pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine { let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { - tcx.output_filenames(LOCAL_CRATE) - .split_dwarf_path(tcx.sess.split_debuginfo(), Some(mod_name)) + tcx.output_filenames(()).split_dwarf_path(tcx.sess.split_debuginfo(), Some(mod_name)) } else { None }; let config = TargetMachineFactoryConfig { split_dwarf_file }; - target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))(config) + target_machine_factory(&tcx.sess, tcx.backend_optimization_level(()))(config) .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise()) } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 053cda1e7cc..bc9d99ed4a1 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -118,24 +118,16 @@ macro_rules! builder_methods_for_value_instructions { } impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { - fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self { - let mut bx = Builder::with_cx(cx); - let llbb = unsafe { - let name = SmallCStr::new(name); - llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr()) - }; - bx.position_at_end(llbb); + fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self { + let bx = Builder::with_cx(cx); + unsafe { + llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); + } bx } - fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { - // Create a fresh builder from the crate context. - let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; - Builder { llbuilder, cx } - } - - fn build_sibling_block(&self, name: &str) -> Self { - Builder::new_block(self.cx, self.llfn(), name) + fn cx(&self) -> &CodegenCx<'ll, 'tcx> { + self.cx } fn llbb(&self) -> &'ll BasicBlock { @@ -144,12 +136,22 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn set_span(&mut self, _span: Span) {} - fn position_at_end(&mut self, llbb: &'ll BasicBlock) { + fn append_block(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &str) -> &'ll BasicBlock { unsafe { - llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb); + let name = SmallCStr::new(name); + llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, name.as_ptr()) } } + fn append_sibling_block(&mut self, name: &str) -> &'ll BasicBlock { + Self::append_block(self.cx, self.llfn(), name) + } + + fn build_sibling_block(&mut self, name: &str) -> Self { + let llbb = self.append_sibling_block(name); + Self::build(self.cx, llbb) + } + fn ret_void(&mut self) { unsafe { llvm::LLVMBuildRetVoid(self.llbuilder); @@ -1144,14 +1146,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) } } - fn cx(&self) -> &CodegenCx<'ll, 'tcx> { - self.cx - } - - unsafe fn delete_basic_block(&mut self, bb: &'ll BasicBlock) { - llvm::LLVMDeleteBasicBlock(bb); - } - fn do_not_inline(&mut self, llret: &'ll Value) { llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); } @@ -1165,6 +1159,12 @@ impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { } impl Builder<'a, 'll, 'tcx> { + fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { + // Create a fresh builder from the crate context. + let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; + Builder { llbuilder, cx } + } + pub fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 30f125ca3be..d2a2e739ff3 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -6,7 +6,7 @@ use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression}; use rustc_codegen_ssa::traits::{ConstMethods, CoverageInfoMethods}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_llvm::RustString; use rustc_middle::mir::coverage::CodeRegion; use rustc_span::Symbol; @@ -265,7 +265,7 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics(); let all_def_ids: DefIdSet = tcx - .mir_keys(LOCAL_CRATE) + .mir_keys(()) .iter() .filter_map(|local_def_id| { let def_id = local_def_id.to_def_id(); @@ -276,7 +276,7 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { }) .collect(); - let codegenned_def_ids = tcx.codegened_and_inlined_items(LOCAL_CRATE); + let codegenned_def_ids = tcx.codegened_and_inlined_items(()); let mut unused_def_ids_by_file: FxHashMap<Symbol, Vec<DefId>> = FxHashMap::default(); for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index afc2bdbfd52..019bf4a09a7 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -223,7 +223,8 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) { let llfn = cx.get_fn(instance); - let mut bx = Builder::new_block(cx, llfn, "unused_function"); + let llbb = Builder::append_block(cx, llfn, "unused_function"); + let mut bx = Builder::build(cx, llbb); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(0); let num_counters = bx.const_u32(1); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 5cf831475d4..0db6659f8e2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -995,9 +995,10 @@ pub fn compile_unit_metadata( let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); let work_dir = tcx.sess.working_dir.to_string_lossy(false); let flags = "\0"; - let out_dir = &tcx.output_filenames(LOCAL_CRATE).out_directory; + let output_filenames = tcx.output_filenames(()); + let out_dir = &output_filenames.out_directory; let split_name = if tcx.sess.target_can_use_split_dwarf() { - tcx.output_filenames(LOCAL_CRATE) + output_filenames .split_dwarf_path(tcx.sess.split_debuginfo(), Some(codegen_unit_name)) .map(|f| out_dir.join(f)) } else { @@ -1058,15 +1059,12 @@ pub fn compile_unit_metadata( if tcx.sess.opts.debugging_opts.profile { let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata); - let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda"); + let default_gcda_path = &output_filenames.with_extension("gcda"); let gcda_path = tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path); let gcov_cu_info = [ - path_to_mdstring( - debug_context.llcontext, - &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"), - ), + path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")), path_to_mdstring(debug_context.llcontext, &gcda_path), cu_desc_metadata, ]; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index b928e903730..2b99a2ebad9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -23,7 +23,7 @@ use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, Variab use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; -use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_index::vec::IndexVec; use rustc_middle::mir; use rustc_middle::ty::layout::HasTyCtxt; @@ -343,7 +343,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if self.sess().opts.optimize != config::OptLevel::No { spflags |= DISPFlags::SPFlagOptimized; } - if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) { + if let Some((id, _)) = self.tcx.entry_fn(()) { if id == def_id { spflags |= DISPFlags::SPFlagMainSubprogram; } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index fc6c1abf4af..22d513d66d1 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -678,7 +678,8 @@ fn gen_fn<'ll, 'tcx>( cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; - let bx = Builder::new_block(cx, llfn, "entry-block"); + let llbb = Builder::append_block(cx, llfn, "entry-block"); + let bx = Builder::build(cx, llbb); codegen(bx); llfn } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 329458773ff..8eef06f018f 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,7 +8,7 @@ #![feature(bool_to_option)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(iter_zip)] diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 32fdde9b42e..bf66040a7eb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1079,7 +1079,6 @@ extern "C" { Fn: &'a Value, Name: *const c_char, ) -> &'a BasicBlock; - pub fn LLVMDeleteBasicBlock(BB: &BasicBlock); // Operations on instructions pub fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>; diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 93059b2323d..4dc9a3f5e41 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -281,8 +281,11 @@ impl<'a> Linker for GccLinker<'a> { } } LinkOutputKind::DynamicPicExe => { - // `-pie` works for both gcc wrapper and ld. - self.cmd.arg("-pie"); + // noop on windows w/ gcc & ld, error w/ lld + if !self.sess.target.is_like_windows { + // `-pie` works for both gcc wrapper and ld. + self.cmd.arg("-pie"); + } } LinkOutputKind::StaticNoPicExe => { // `-static` works for both gcc wrapper and ld. @@ -347,7 +350,7 @@ impl<'a> Linker for GccLinker<'a> { // has -needed-l{} / -needed_library {} // but we have no way to detect that here. self.sess.warn("`as-needed` modifier not implemented yet for ld64"); - } else if self.sess.target.linker_is_gnu { + } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--no-as-needed"); } else { self.sess.warn("`as-needed` modifier not supported for current linker"); @@ -358,7 +361,7 @@ impl<'a> Linker for GccLinker<'a> { if !as_needed { if self.sess.target.is_like_osx { // See above FIXME comment - } else if self.sess.target.linker_is_gnu { + } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--as-needed"); } } @@ -469,7 +472,7 @@ impl<'a> Linker for GccLinker<'a> { // eliminate the metadata. If we're building an executable, however, // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. - } else if !keep_metadata { + } else if self.sess.target.linker_is_gnu && !keep_metadata { self.linker_arg("--gc-sections"); } } @@ -477,9 +480,7 @@ impl<'a> Linker for GccLinker<'a> { fn no_gc_sections(&mut self) { if self.sess.target.is_like_osx { self.linker_arg("-no_dead_strip"); - } else if self.sess.target.is_like_solaris { - self.linker_arg("-zrecord"); - } else { + } else if self.sess.target.linker_is_gnu { self.linker_arg("--no-gc-sections"); } } @@ -692,7 +693,7 @@ impl<'a> Linker for GccLinker<'a> { } fn add_as_needed(&mut self) { - if self.sess.target.linker_is_gnu { + if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows { self.linker_arg("--as-needed"); } else if self.sess.target.is_like_solaris { // -z ignore is the Solaris equivalent to the GNU ld --as-needed option @@ -1303,7 +1304,7 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> { } } - let formats = tcx.dependency_formats(LOCAL_CRATE); + let formats = tcx.dependency_formats(()); let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap(); for (index, dep_format) in deps.iter().enumerate() { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 2bff2fcba43..14d6f0ba147 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -4,7 +4,7 @@ use rustc_ast::expand::allocator::ALLOCATOR_METHODS; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::Node; use rustc_index::vec::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -60,7 +60,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap< tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE); let mut reachable_non_generics: DefIdMap<_> = tcx - .reachable_set(LOCAL_CRATE) + .reachable_set(()) .iter() .filter_map(|&def_id| { // We want to ignore some FFI functions that are not exposed from @@ -133,12 +133,12 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap< }) .collect(); - if let Some(id) = tcx.proc_macro_decls_static(LOCAL_CRATE) { - reachable_non_generics.insert(id, SymbolExportLevel::C); + if let Some(id) = tcx.proc_macro_decls_static(()) { + reachable_non_generics.insert(id.to_def_id(), SymbolExportLevel::C); } - if let Some(id) = tcx.plugin_registrar_fn(LOCAL_CRATE) { - reachable_non_generics.insert(id, SymbolExportLevel::C); + if let Some(id) = tcx.plugin_registrar_fn(()) { + reachable_non_generics.insert(id.to_def_id(), SymbolExportLevel::C); } reachable_non_generics @@ -174,7 +174,7 @@ fn exported_symbols_provider_local( .map(|(&def_id, &level)| (ExportedSymbol::NonGeneric(def_id), level)) .collect(); - if tcx.entry_fn(LOCAL_CRATE).is_some() { + if tcx.entry_fn(()).is_some() { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, "main")); symbols.push((exported_symbol, SymbolExportLevel::C)); @@ -230,7 +230,7 @@ fn exported_symbols_provider_local( // external linkage is enough for monomorphization to be linked to. let need_visibility = tcx.sess.target.dynamic_linking && !tcx.sess.target.only_cdylib; - let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); + let (_, cgus) = tcx.collect_and_partition_mono_items(()); for (mono_item, &(linkage, visibility)) in cgus.iter().flat_map(|cgu| cgu.items().iter()) { if linkage != Linkage::External { @@ -275,11 +275,9 @@ fn exported_symbols_provider_local( fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, - cnum: CrateNum, + (): (), ) -> DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> { - debug_assert!(cnum == LOCAL_CRATE); - - let cnums = tcx.all_crate_nums(LOCAL_CRATE); + let cnums = tcx.all_crate_nums(()); let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default(); @@ -341,7 +339,7 @@ fn upstream_monomorphizations_for_provider( def_id: DefId, ) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> { debug_assert!(!def_id.is_local()); - tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id) + tcx.upstream_monomorphizations(()).get(&def_id) } fn upstream_drop_glue_for_provider<'tcx>( @@ -355,12 +353,8 @@ fn upstream_drop_glue_for_provider<'tcx>( } } -fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - if let Some(def_id) = def_id.as_local() { - !tcx.reachable_set(LOCAL_CRATE).contains(&def_id) - } else { - bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id) - } +fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + !tcx.reachable_set(()).contains(&def_id) } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index fb0662a3993..49774dc6d5c 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -482,7 +482,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>( codegen_worker_receive, shared_emitter_main, future: coordinator_thread, - output_filenames: tcx.output_filenames(LOCAL_CRATE), + output_filenames: tcx.output_filenames(()), } } @@ -1042,7 +1042,7 @@ fn start_executing_work<B: ExtraBackendMethods>( // If we know that we won’t be doing codegen, create target machines without optimisation. config::OptLevel::No } else { - tcx.backend_optimization_level(LOCAL_CRATE) + tcx.backend_optimization_level(()) }; let cgcx = CodegenContext::<B> { backend: backend.clone(), @@ -1061,7 +1061,7 @@ fn start_executing_work<B: ExtraBackendMethods>( cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(), coordinator_send, diag_emitter: shared_emitter.clone(), - output_filenames: tcx.output_filenames(LOCAL_CRATE), + output_filenames: tcx.output_filenames(()), regular_module_config: regular_config, metadata_module_config: metadata_config, allocator_module_config: allocator_config, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a9ab075d3db..b44e74d5ae8 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -347,7 +347,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, ) -> Option<Bx::Function> { - let main_def_id = cx.tcx().entry_fn(LOCAL_CRATE).map(|(def_id, _)| def_id)?; + let (main_def_id, entry_type) = cx.tcx().entry_fn(())?; let main_is_local = main_def_id.is_local(); let instance = Instance::mono(cx.tcx(), main_def_id); @@ -364,10 +364,9 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let main_llfn = cx.get_fn_addr(instance); - return cx.tcx().entry_fn(LOCAL_CRATE).map(|(_, et)| { - let use_start_lang_item = EntryFnType::Start != et; - create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item) - }); + let use_start_lang_item = EntryFnType::Start != entry_type; + let entry_fn = create_entry_fn::<Bx>(cx, main_llfn, main_def_id, use_start_lang_item); + return Some(entry_fn); fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, @@ -409,7 +408,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx.set_frame_pointer_elimination(llfn); cx.apply_target_cpu_attr(llfn); - let mut bx = Bx::new_block(&cx, llfn, "top"); + let llbb = Bx::append_block(&cx, llfn, "top"); + let mut bx = Bx::build(&cx, llbb); bx.insert_reference_to_gdb_debug_scripts_section_global(); @@ -486,7 +486,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // Run the monomorphization collector and partition the collected items into // codegen units. - let codegen_units = tcx.collect_and_partition_mono_items(LOCAL_CRATE).1; + let codegen_units = tcx.collect_and_partition_mono_items(()).1; // Force all codegen_unit queries so they are already either red or green // when compile_codegen_unit accesses them. We are not able to re-execute @@ -511,7 +511,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // linkage, then it's already got an allocator shim and we'll be using that // one instead. If nothing exists then it's our job to generate the // allocator! - let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE).iter().any(|(_, list)| { + let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| { use rustc_middle::middle::dependency_format::Linkage; list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); @@ -768,7 +768,7 @@ impl CrateInfo { used_crate_source: Default::default(), lang_item_to_crate: Default::default(), missing_lang_items: Default::default(), - dependency_formats: tcx.dependency_formats(LOCAL_CRATE), + dependency_formats: tcx.dependency_formats(()), }; let lang_items = tcx.lang_items(); diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 955f658eb1c..1fa60612d26 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -219,8 +219,6 @@ pub fn asm_const_to_str<'tcx>( ty::IntTy::I128 => (value as i128).to_string(), ty::IntTy::Isize => unreachable!(), }, - ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(), - ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(), _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty), } } diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index 4458fd68678..08442c588f8 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -49,9 +49,9 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn create(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, is_used: bool) -> Self { - let coverageinfo = tcx.coverageinfo(instance.def_id()); + let coverageinfo = tcx.coverageinfo(instance.def); debug!( - "FunctionCoverage::new(instance={:?}) has coverageinfo={:?}. is_used={}", + "FunctionCoverage::create(instance={:?}) has coverageinfo={:?}. is_used={}", instance, coverageinfo, is_used ); Self { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 2bd35fe9b14..93200bd1f26 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_span::source_map::Span; use rustc_span::{sym, Symbol}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; -use rustc_target::abi::{self, LayoutOf}; +use rustc_target::abi::{self, HasDataLayout, LayoutOf}; use rustc_target::spec::abi::Abi; /// Used by `FunctionCx::codegen_terminator` for emitting common patterns @@ -32,13 +32,34 @@ struct TerminatorCodegenHelper<'tcx> { } impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { - /// Returns the associated funclet from `FunctionCx::funclets` for the - /// `funclet_bb` member if it is not `None`. + /// Returns the appropriate `Funclet` for the current funclet, if on MSVC, + /// either already previously cached, or newly created, by `landing_pad_for`. fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>( &self, - fx: &'b FunctionCx<'a, 'tcx, Bx>, + fx: &'b mut FunctionCx<'a, 'tcx, Bx>, ) -> Option<&'b Bx::Funclet> { - self.funclet_bb.and_then(|funcl| fx.funclets[funcl].as_ref()) + let funclet_bb = self.funclet_bb?; + if base::wants_msvc_seh(fx.cx.tcx().sess) { + // If `landing_pad_for` hasn't been called yet to create the `Funclet`, + // it has to be now. This may not seem necessary, as RPO should lead + // to all the unwind edges being visited (and so to `landing_pad_for` + // getting called for them), before building any of the blocks inside + // the funclet itself - however, if MIR contains edges that end up not + // being needed in the LLVM IR after monomorphization, the funclet may + // be unreachable, and we don't have yet a way to skip building it in + // such an eventuality (which may be a better solution than this). + if fx.funclets[funclet_bb].is_none() { + fx.landing_pad_for(funclet_bb); + } + + Some( + fx.funclets[funclet_bb] + .as_ref() + .expect("landing_pad_for didn't also create funclets entry"), + ) + } else { + None + } } fn lltarget<Bx: BuilderMethods<'a, 'tcx>>( @@ -47,17 +68,17 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { target: mir::BasicBlock, ) -> (Bx::BasicBlock, bool) { let span = self.terminator.source_info.span; - let lltarget = fx.blocks[target]; + let lltarget = fx.llbb(target); let target_funclet = fx.cleanup_kinds[target].funclet_bb(target); match (self.funclet_bb, target_funclet) { (None, None) => (lltarget, false), (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => { (lltarget, false) } - // jump *into* cleanup - need a landing pad if GNU - (None, Some(_)) => (fx.landing_pad_to(target), false), + // jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC + (None, Some(_)) => (fx.landing_pad_for(target), false), (Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator), - (Some(_), Some(_)) => (fx.landing_pad_to(target), true), + (Some(_), Some(_)) => (fx.landing_pad_for(target), true), } } @@ -112,13 +133,13 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { - let ret_bx = if let Some((_, target)) = destination { - fx.blocks[target] + let ret_llbb = if let Some((_, target)) = destination { + fx.llbb(target) } else { fx.unreachable_block() }; let invokeret = - bx.invoke(fn_ptr, &llargs, ret_bx, self.llblock(fx, cleanup), self.funclet(fx)); + bx.invoke(fn_ptr, &llargs, ret_llbb, self.llblock(fx, cleanup), self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, invokeret); if let Some((ret_dest, target)) = destination { @@ -365,7 +386,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Create the failure block and the conditional branch to it. let lltarget = helper.llblock(self, target); - let panic_block = self.new_block("panic"); + let panic_block = bx.build_sibling_block("panic"); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -1170,38 +1191,88 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - /// Returns the landing-pad wrapper around the given basic block. - /// - /// No-op in MSVC SEH scheme. - fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> Bx::BasicBlock { - if let Some(block) = self.landing_pads[target_bb] { - return block; + /// Returns the landing/cleanup pad wrapper around the given basic block. + // FIXME(eddyb) rename this to `eh_pad_for`. + fn landing_pad_for(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { + if let Some(landing_pad) = self.landing_pads[bb] { + return landing_pad; } - let block = self.blocks[target_bb]; - let landing_pad = self.landing_pad_uncached(block); - self.landing_pads[target_bb] = Some(landing_pad); + let landing_pad = self.landing_pad_for_uncached(bb); + self.landing_pads[bb] = Some(landing_pad); landing_pad } - fn landing_pad_uncached(&mut self, target_bb: Bx::BasicBlock) -> Bx::BasicBlock { + // FIXME(eddyb) rename this to `eh_pad_for_uncached`. + fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { + let llbb = self.llbb(bb); if base::wants_msvc_seh(self.cx.sess()) { - span_bug!(self.mir.span, "landing pad was not inserted?") - } - - let mut bx = self.new_block("cleanup"); + let funclet; + let ret_llbb; + match self.mir[bb].terminator.as_ref().map(|t| &t.kind) { + // This is a basic block that we're aborting the program for, + // notably in an `extern` function. These basic blocks are inserted + // so that we assert that `extern` functions do indeed not panic, + // and if they do we abort the process. + // + // On MSVC these are tricky though (where we're doing funclets). If + // we were to do a cleanuppad (like below) the normal functions like + // `longjmp` would trigger the abort logic, terminating the + // program. Instead we insert the equivalent of `catch(...)` for C++ + // which magically doesn't trigger when `longjmp` files over this + // frame. + // + // Lots more discussion can be found on #48251 but this codegen is + // modeled after clang's for: + // + // try { + // foo(); + // } catch (...) { + // bar(); + // } + Some(&mir::TerminatorKind::Abort) => { + let mut cs_bx = self.new_block(&format!("cs_funclet{:?}", bb)); + let mut cp_bx = self.new_block(&format!("cp_funclet{:?}", bb)); + ret_llbb = cs_bx.llbb(); + + let cs = cs_bx.catch_switch(None, None, 1); + cs_bx.add_handler(cs, cp_bx.llbb()); + + // The "null" here is actually a RTTI type descriptor for the + // C++ personality function, but `catch (...)` has no type so + // it's null. The 64 here is actually a bitfield which + // represents that this is a catch-all block. + let null = cp_bx.const_null( + cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space), + ); + let sixty_four = cp_bx.const_i32(64); + funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]); + cp_bx.br(llbb); + } + _ => { + let mut cleanup_bx = self.new_block(&format!("funclet_{:?}", bb)); + ret_llbb = cleanup_bx.llbb(); + funclet = cleanup_bx.cleanup_pad(None, &[]); + cleanup_bx.br(llbb); + } + } + self.funclets[bb] = Some(funclet); + ret_llbb + } else { + let mut bx = self.new_block("cleanup"); - let llpersonality = self.cx.eh_personality(); - let llretty = self.landing_pad_type(); - let lp = bx.landing_pad(llretty, llpersonality, 1); - bx.set_cleanup(lp); + let llpersonality = self.cx.eh_personality(); + let llretty = self.landing_pad_type(); + let lp = bx.landing_pad(llretty, llpersonality, 1); + bx.set_cleanup(lp); - let slot = self.get_personality_slot(&mut bx); - slot.storage_live(&mut bx); - Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot); + let slot = self.get_personality_slot(&mut bx); + slot.storage_live(&mut bx); + Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot); - bx.br(target_bb); - bx.llbb() + bx.br(llbb); + bx.llbb() + } } fn landing_pad_type(&self) -> Bx::Type { @@ -1218,14 +1289,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - pub fn new_block(&self, name: &str) -> Bx { - Bx::new_block(self.cx, self.llfn, name) + // FIXME(eddyb) replace with `build_sibling_block`/`append_sibling_block` + // (which requires having a `Bx` already, and not all callers do). + fn new_block(&self, name: &str) -> Bx { + let llbb = Bx::append_block(self.cx, self.llfn, name); + Bx::build(self.cx, llbb) + } + + /// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already + /// cached in `self.cached_llbbs`, or created on demand (and cached). + // FIXME(eddyb) rename `llbb` and other `ll`-prefixed things to use a + // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbb`). + pub fn llbb(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { + self.cached_llbbs[bb].unwrap_or_else(|| { + // FIXME(eddyb) only name the block if `fewer_names` is `false`. + let llbb = Bx::append_block(self.cx, self.llfn, &format!("{:?}", bb)); + self.cached_llbbs[bb] = Some(llbb); + llbb + }) } - pub fn build_block(&self, bb: mir::BasicBlock) -> Bx { - let mut bx = Bx::with_cx(self.cx); - bx.position_at_end(self.blocks[bb]); - bx + pub fn build_block(&mut self, bb: mir::BasicBlock) -> Bx { + let llbb = self.llbb(bb); + Bx::build(self.cx, llbb) } fn make_return_dest( diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs index 621ec0519c9..a283bf1de76 100644 --- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs @@ -31,7 +31,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.add_coverage_counter(instance, id, code_region); } - let coverageinfo = bx.tcx().coverageinfo(instance.def_id()); + let coverageinfo = bx.tcx().coverageinfo(instance.def); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_source_hash); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 91df67b53d2..3bbc481b610 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -1,4 +1,3 @@ -use crate::base; use crate::traits::*; use rustc_errors::ErrorReported; use rustc_middle::mir; @@ -6,14 +5,12 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_target::abi::call::{FnAbi, PassMode}; -use rustc_target::abi::HasDataLayout; use std::iter; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; -use self::analyze::CleanupKind; use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo}; use self::place::PlaceRef; use rustc_middle::mir::traversal; @@ -43,18 +40,22 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// then later loaded when generating the DIVERGE_BLOCK. personality_slot: Option<PlaceRef<'tcx, Bx::Value>>, - /// A `Block` for each MIR `BasicBlock` - blocks: IndexVec<mir::BasicBlock, Bx::BasicBlock>, + /// A backend `BasicBlock` for each MIR `BasicBlock`, created lazily + /// as-needed (e.g. RPO reaching it or another block branching to it). + // FIXME(eddyb) rename `llbbs` and other `ll`-prefixed things to use a + // more backend-agnostic prefix such as `cg` (i.e. this would be `cgbbs`). + cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>, /// The funclet status of each basic block cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>, - /// When targeting MSVC, this stores the cleanup info for each funclet - /// BB. This is initialized as we compute the funclets' head block in RPO. + /// When targeting MSVC, this stores the cleanup info for each funclet BB. + /// This is initialized at the same time as the `landing_pads` entry for the + /// funclets' head block, i.e. when needed by an unwind / `cleanup_ret` edge. funclets: IndexVec<mir::BasicBlock, Option<Bx::Funclet>>, - /// This stores the landing-pad block for a given BB, computed lazily on GNU - /// and eagerly on MSVC. + /// This stores the cached landing/cleanup pad block for a given BB. + // FIXME(eddyb) rename this to `eh_pads`. landing_pads: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>, /// Cached unreachable block @@ -143,7 +144,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir); - let mut bx = Bx::new_block(cx, llfn, "start"); + let start_llbb = Bx::append_block(cx, llfn, "start"); + let mut bx = Bx::build(cx, start_llbb); if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) { bx.set_personality_fn(cx.eh_personality()); @@ -153,19 +155,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Allocate a `Block` for every basic block, except // the start block, if nothing loops back to it. let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty(); - let block_bxs: IndexVec<mir::BasicBlock, Bx::BasicBlock> = mir - .basic_blocks() - .indices() - .map(|bb| { - if bb == mir::START_BLOCK && !reentrant_start_block { - bx.llbb() - } else { - bx.build_sibling_block(&format!("{:?}", bb)).llbb() - } - }) - .collect(); + let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = + mir.basic_blocks() + .indices() + .map(|bb| { + if bb == mir::START_BLOCK && !reentrant_start_block { + Some(start_llbb) + } else { + None + } + }) + .collect(); - let (landing_pads, funclets) = create_funclets(&mir, &mut bx, &cleanup_kinds, &block_bxs); let mut fx = FunctionCx { instance, mir, @@ -173,11 +174,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fn_abi, cx, personality_slot: None, - blocks: block_bxs, + cached_llbbs, unreachable_block: None, cleanup_kinds, - landing_pads, - funclets, + landing_pads: IndexVec::from_elem(None, mir.basic_blocks()), + funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks().len()), locals: IndexVec::new(), debug_context, per_local_var_debug_info: None, @@ -248,100 +249,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Branch to the START block, if it's not the entry block. if reentrant_start_block { - bx.br(fx.blocks[mir::START_BLOCK]); + bx.br(fx.llbb(mir::START_BLOCK)); } - let rpo = traversal::reverse_postorder(&mir); - let mut visited = BitSet::new_empty(mir.basic_blocks().len()); - // Codegen the body of each block using reverse postorder - for (bb, _) in rpo { - visited.insert(bb.index()); + // FIXME(eddyb) reuse RPO iterator between `analysis` and this. + for (bb, _) in traversal::reverse_postorder(&mir) { fx.codegen_block(bb); } - - // Remove blocks that haven't been visited, or have no - // predecessors. - for bb in mir.basic_blocks().indices() { - // Unreachable block - if !visited.contains(bb.index()) { - debug!("codegen_mir: block {:?} was not visited", bb); - unsafe { - bx.delete_basic_block(fx.blocks[bb]); - } - } - } -} - -fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - mir: &'tcx mir::Body<'tcx>, - bx: &mut Bx, - cleanup_kinds: &IndexVec<mir::BasicBlock, CleanupKind>, - block_bxs: &IndexVec<mir::BasicBlock, Bx::BasicBlock>, -) -> ( - IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>, - IndexVec<mir::BasicBlock, Option<Bx::Funclet>>, -) { - iter::zip(block_bxs.iter_enumerated(), cleanup_kinds) - .map(|((bb, &llbb), cleanup_kind)| { - match *cleanup_kind { - CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {} - _ => return (None, None), - } - - let funclet; - let ret_llbb; - match mir[bb].terminator.as_ref().map(|t| &t.kind) { - // This is a basic block that we're aborting the program for, - // notably in an `extern` function. These basic blocks are inserted - // so that we assert that `extern` functions do indeed not panic, - // and if they do we abort the process. - // - // On MSVC these are tricky though (where we're doing funclets). If - // we were to do a cleanuppad (like below) the normal functions like - // `longjmp` would trigger the abort logic, terminating the - // program. Instead we insert the equivalent of `catch(...)` for C++ - // which magically doesn't trigger when `longjmp` files over this - // frame. - // - // Lots more discussion can be found on #48251 but this codegen is - // modeled after clang's for: - // - // try { - // foo(); - // } catch (...) { - // bar(); - // } - Some(&mir::TerminatorKind::Abort) => { - let mut cs_bx = bx.build_sibling_block(&format!("cs_funclet{:?}", bb)); - let mut cp_bx = bx.build_sibling_block(&format!("cp_funclet{:?}", bb)); - ret_llbb = cs_bx.llbb(); - - let cs = cs_bx.catch_switch(None, None, 1); - cs_bx.add_handler(cs, cp_bx.llbb()); - - // The "null" here is actually a RTTI type descriptor for the - // C++ personality function, but `catch (...)` has no type so - // it's null. The 64 here is actually a bitfield which - // represents that this is a catch-all block. - let null = bx.const_null( - bx.type_i8p_ext(bx.cx().data_layout().instruction_address_space), - ); - let sixty_four = bx.const_i32(64); - funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]); - cp_bx.br(llbb); - } - _ => { - let mut cleanup_bx = bx.build_sibling_block(&format!("funclet_{:?}", bb)); - ret_llbb = cleanup_bx.llbb(); - funclet = cleanup_bx.cleanup_pad(None, &[]); - cleanup_bx.br(llbb); - } - }; - - (Some(ret_llbb), Some(funclet)) - }) - .unzip() } /// Produces, for each argument, a `Value` pointing at the diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 1bc05f30e5c..29b2db5d4d7 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -40,14 +40,21 @@ pub trait BuilderMethods<'a, 'tcx>: + HasParamEnv<'tcx> + HasTargetSpec { - fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self; - fn with_cx(cx: &'a Self::CodegenCx) -> Self; - fn build_sibling_block(&self, name: &str) -> Self; + fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self; + fn cx(&self) -> &Self::CodegenCx; fn llbb(&self) -> Self::BasicBlock; + fn set_span(&mut self, span: Span); - fn position_at_end(&mut self, llbb: Self::BasicBlock); + // FIXME(eddyb) replace uses of this with `append_sibling_block`. + fn append_block(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &str) -> Self::BasicBlock; + + fn append_sibling_block(&mut self, name: &str) -> Self::BasicBlock; + + // FIXME(eddyb) replace with callers using `append_sibling_block`. + fn build_sibling_block(&mut self, name: &str) -> Self; + fn ret_void(&mut self); fn ret(&mut self, v: Self::Value); fn br(&mut self, dest: Self::BasicBlock); @@ -291,6 +298,5 @@ pub trait BuilderMethods<'a, 'tcx>: ) -> Self::Value; fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; - unsafe fn delete_basic_block(&mut self, bb: Self::BasicBlock); fn do_not_inline(&mut self, llret: Self::Value); } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 18114634209..c9b36dd0c24 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -21,7 +21,6 @@ use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{ErrorReported, PResult}; use rustc_feature::find_gated_cfg; -use rustc_hir::def_id::LOCAL_CRATE; use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; @@ -389,7 +388,7 @@ fn run_compiler( } queries.global_ctxt()?.peek_mut().enter(|tcx| { - let result = tcx.analysis(LOCAL_CRATE); + let result = tcx.analysis(()); if sess.opts.debugging_opts.save_analysis { let crate_name = queries.crate_name()?.peek().clone(); sess.time("save_analysis", || { diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index e0c140b143b..370ec053cbb 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -4,7 +4,6 @@ use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir_pretty as pprust_hir; use rustc_middle::hir::map as hir_map; use rustc_middle::ty::{self, TyCtxt}; @@ -74,7 +73,7 @@ where f(&annotation, tcx.hir().krate()) } PpHirMode::Typed => { - abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); + abort_on_err(tcx.analysis(()), tcx.sess); let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) }; tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir().krate())) @@ -475,7 +474,7 @@ fn print_with_analysis( ppm: PpMode, ofile: Option<&Path>, ) -> Result<(), ErrorReported> { - tcx.analysis(LOCAL_CRATE)?; + tcx.analysis(())?; let out = match ppm { Mir => { diff --git a/compiler/rustc_error_codes/src/error_codes/E0277.md b/compiler/rustc_error_codes/src/error_codes/E0277.md index 9f6db6ed7a2..5f05b59d5a6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0277.md +++ b/compiler/rustc_error_codes/src/error_codes/E0277.md @@ -29,16 +29,16 @@ trait Foo { fn bar(&self); } -fn some_func<T: Foo>(foo: T) { - foo.bar(); // we can now use this method since i32 implements the - // Foo trait -} - // we implement the trait on the i32 type impl Foo for i32 { fn bar(&self) {} } +fn some_func<T: Foo>(foo: T) { + foo.bar(); // we can now use this method since i32 implements the + // Foo trait +} + fn main() { some_func(5i32); // ok! } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f53ce7ceace..65352f0bc6e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,7 +5,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(backtrace)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(format_args_capture)] #![feature(iter_zip)] #![feature(nll)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e8642a52749..eef71e096a5 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -281,6 +281,8 @@ declare_features! ( (accepted, or_patterns, "1.53.0", Some(54883), None), /// Allows defining identifiers beyond ASCII. (accepted, non_ascii_idents, "1.53.0", Some(55467), None), + /// Allows arbitrary expressions in key-value attributes at parse time. + (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 535cb132766..2cef46a844a 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -601,9 +601,6 @@ declare_features! ( /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (active, capture_disjoint_fields, "1.49.0", Some(53488), None), - /// Allows arbitrary expressions in key-value attributes at parse time. - (active, extended_key_value_attributes, "1.50.0", Some(78835), None), - /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`). (active, const_generics_defaults, "1.51.0", Some(44580), None), @@ -650,6 +647,9 @@ declare_features! ( /// Allows unsizing coercions in `const fn`. (active, const_fn_unsize, "1.53.0", Some(64992), None), + /// Allows `async {}` expressions in const contexts. + (active, const_async_blocks, "1.53.0", Some(85368), None), + /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), @@ -668,6 +668,9 @@ declare_features! ( /// Allows specifying the as-needed link modifier (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), + /// Allows unnamed fields of struct and union type + (active, unnamed_fields, "1.53.0", Some(49804), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -692,7 +695,6 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::repr128, sym::unsized_locals, sym::capture_disjoint_fields, - sym::const_generics_defaults, sym::inherent_associated_types, sym::type_alias_impl_trait, sym::native_link_modifiers, @@ -700,6 +702,8 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::native_link_modifiers_verbatim, sym::native_link_modifiers_whole_archive, sym::native_link_modifiers_as_needed, + sym::rustc_insignificant_dtor, + sym::unnamed_fields, ]; /// Some features are not allowed to be used together at the same time, if diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 51d69167f7b..e7e128f8a9b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -556,6 +556,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), + rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)), rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 7b788b13b9f..0b8535f8ca5 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -308,12 +308,12 @@ language_item_table! { Termination, sym::termination, termination, Target::Trait; - Try, kw::Try, try_trait, Target::Trait; + Try, sym::Try, try_trait, Target::Trait; // Language items from AST lowering - TryFromError, sym::from_error, from_error_fn, Target::Method(MethodKind::Trait { body: false }); - TryFromOk, sym::from_ok, from_ok_fn, Target::Method(MethodKind::Trait { body: false }); - TryIntoResult, sym::into_result, into_result_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }); + TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }); PollReady, sym::Ready, poll_ready_variant, Target::Variant; PollPending, sym::Pending, poll_pending_variant, Target::Variant; @@ -331,6 +331,9 @@ language_item_table! { ResultOk, sym::Ok, result_ok_variant, Target::Variant; ResultErr, sym::Err, result_err_variant, Target::Variant; + ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant; + ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant; + IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }); IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}); diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 65c99535c4e..71e997994de 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,7 @@ #![feature(crate_visibility_modifier)] #![feature(const_panic)] -#![feature(extended_key_value_attributes)] +#![cfg_attr(bootstrap, feature(extended_key_value_attributes))] #![feature(in_band_lifetimes)] #![feature(once_cell)] #![cfg_attr(bootstrap, feature(or_patterns))] diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index 5fb2c1cb9c9..8220eb6c657 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -36,7 +36,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { } let available_cgus = tcx - .collect_and_partition_mono_items(LOCAL_CRATE) + .collect_and_partition_mono_items(()) .1 .iter() .map(|cgu| cgu.name().to_string()) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 9ffcddfae99..49359130162 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -3,7 +3,6 @@ use self::CombineMapType::*; use self::UndoLog::*; -use super::unify_key; use super::{ InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin, }; @@ -12,9 +11,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; -use rustc_data_structures::unify::UnifyKey; use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; +use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion}; use rustc_middle::ty::ReStatic; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReLateBound, ReVar}; @@ -54,7 +53,7 @@ pub struct RegionConstraintStorage<'tcx> { /// code is iterating to a fixed point, because otherwise we sometimes /// would wind up with a fresh stream of region variables that have been /// equated but appear distinct. - pub(super) unification_table: ut::UnificationTableStorage<ty::RegionVid>, + pub(super) unification_table: ut::UnificationTableStorage<RegionVidKey<'tcx>>, /// a flag set to true when we perform any unifications; this is used /// to micro-optimize `take_and_reset_data` @@ -407,8 +406,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { // `RegionConstraintData` contains the relationship here. if *any_unifications { *any_unifications = false; - self.unification_table() - .reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid }); + self.unification_table().reset_unifications(|_| UnifiedRegion(None)); } data @@ -435,8 +433,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { ) -> RegionVid { let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); - let u_vid = self.unification_table().new_key(unify_key::RegionVidKey { min_vid: vid }); - assert_eq!(vid, u_vid); + let u_vid = self.unification_table().new_key(UnifiedRegion(None)); + assert_eq!(vid, u_vid.vid); self.undo_log.push(AddVar(vid)); debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin); vid @@ -498,10 +496,18 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { self.make_subregion(origin.clone(), sub, sup); self.make_subregion(origin, sup, sub); - if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) { - debug!("make_eqregion: uniying {:?} with {:?}", sub, sup); - self.unification_table().union(sub, sup); - self.any_unifications = true; + match (sub, sup) { + (&ty::ReVar(sub), &ty::ReVar(sup)) => { + debug!("make_eqregion: unifying {:?} with {:?}", sub, sup); + self.unification_table().union(sub, sup); + self.any_unifications = true; + } + (&ty::ReVar(vid), value) | (value, &ty::ReVar(vid)) => { + debug!("make_eqregion: unifying {:?} with {:?}", vid, value); + self.unification_table().union_value(vid, UnifiedRegion(Some(value))); + self.any_unifications = true; + } + (_, _) => {} } } } @@ -617,8 +623,29 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } - pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid { - self.unification_table().probe_value(rid).min_vid + /// Resolves the passed RegionVid to the root RegionVid in the unification table + pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid { + self.unification_table().find(rid).vid + } + + /// If the Region is a `ReVar`, then resolves it either to the root value in + /// the unification table, if it exists, or to the root `ReVar` in the table. + /// If the Region is not a `ReVar`, just returns the Region itself. + pub fn opportunistic_resolve_region( + &mut self, + tcx: TyCtxt<'tcx>, + region: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + match region { + ty::ReVar(rid) => { + let unified_region = self.unification_table().probe_value(*rid); + unified_region.0.unwrap_or_else(|| { + let root = self.unification_table().find(*rid).vid; + tcx.reuse_or_mk_region(region, ty::ReVar(root)) + }) + } + _ => region, + } } fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { @@ -673,8 +700,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self, value_count: usize, ) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) { - let range = RegionVid::from_index(value_count as u32) - ..RegionVid::from_index(self.unification_table.len() as u32); + let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len()); ( range.clone(), (range.start.index()..range.end.index()) @@ -696,7 +722,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } #[inline] - fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> { + fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> { ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log) } } diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index f41e872e004..5ad2519a93c 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -3,6 +3,7 @@ use std::marker::PhantomData; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::unify as ut; +use rustc_middle::infer::unify_key::RegionVidKey; use rustc_middle::ty; use crate::{ @@ -22,7 +23,7 @@ pub(crate) enum UndoLog<'tcx> { IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>), FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>), RegionConstraintCollector(region_constraints::UndoLog<'tcx>), - RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>), + RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>), ProjectionCache(traits::UndoLog<'tcx>), PushRegionObligation, } @@ -55,7 +56,7 @@ impl_from! { ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>), - RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>), + RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>), ProjectionCache(traits::UndoLog<'tcx>), } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 06bec91501f..e2220e3b60d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -12,7 +12,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; -use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::Crate; use rustc_lint::LintStore; use rustc_metadata::creader::CStore; @@ -805,9 +805,7 @@ pub fn create_global_ctxt<'tcx>( /// Runs the resolution, type-checking, region checking and other /// miscellaneous analysis passes on the crate. -fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { - assert_eq!(cnum, LOCAL_CRATE); - +fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { rustc_passes::hir_id_validator::check_crate(tcx); let sess = tcx.sess; @@ -816,14 +814,13 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("misc_checking_1", || { parallel!( { - entry_point = sess - .time("looking_for_entry_point", || rustc_passes::entry::find_entry_point(tcx)); + entry_point = sess.time("looking_for_entry_point", || tcx.entry_fn(())); - sess.time("looking_for_plugin_registrar", || { - plugin::build::find_plugin_registrar(tcx) - }); + sess.time("looking_for_plugin_registrar", || tcx.ensure().plugin_registrar_fn(())); - sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx)); + sess.time("looking_for_derive_registrar", || { + tcx.ensure().proc_macro_decls_static(()) + }); let cstore = tcx .cstore_as_any() @@ -903,11 +900,11 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().privacy_access_levels(LOCAL_CRATE); + tcx.ensure().privacy_access_levels(()); parallel!( { - tcx.ensure().check_private_in_public(LOCAL_CRATE); + tcx.ensure().check_private_in_public(()); }, { sess.time("death_checking", || rustc_passes::dead::check_crate(tcx)); diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs index 4637055a82d..88cf6275ebb 100644 --- a/compiler/rustc_interface/src/proc_macro_decls.rs +++ b/compiler/rustc_interface/src/proc_macro_decls.rs @@ -1,21 +1,15 @@ use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; -pub fn find(tcx: TyCtxt<'_>) -> Option<DefId> { - tcx.proc_macro_decls_static(LOCAL_CRATE) -} - -fn proc_macro_decls_static(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> { - assert_eq!(cnum, LOCAL_CRATE); - +fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { let mut finder = Finder { tcx, decls: None }; tcx.hir().krate().visit_all_item_likes(&mut finder); - finder.decls.map(|id| tcx.hir().local_def_id(id).to_def_id()) + finder.decls.map(|id| tcx.hir().local_def_id(id)) } struct Finder<'tcx> { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index bc94fb67ac3..92d05e48068 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -285,7 +285,7 @@ impl<'tcx> Queries<'tcx> { self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { - tcx.analysis(LOCAL_CRATE).ok(); + tcx.analysis(()).ok(); // Don't do code generation if there were any errors self.session().compile_status()?; @@ -302,7 +302,7 @@ impl<'tcx> Queries<'tcx> { /// to write UI tests that actually test that compilation succeeds without reporting /// an error. fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { - let def_id = match tcx.entry_fn(LOCAL_CRATE) { + let def_id = match tcx.entry_fn(()) { Some((def_id, _)) => def_id, _ => return, }; diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index fd29053433e..7b1660b501b 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -922,7 +922,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { } } -/// Returns a version string such as "rustc 1.46.0 (04488afe3 2020-08-24)" +/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" pub fn version_str() -> Option<&'static str> { option_env!("CFG_VERSION") } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index d325b5fe7f8..e504662bb5e 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -18,7 +18,7 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc_ast as ast; use rustc_data_structures::sync::{join, par_iter, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::map::Map; @@ -375,7 +375,7 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>( module_def_id: LocalDefId, pass: T, ) { - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); + let access_levels = &tcx.privacy_access_levels(()); let context = LateContext { tcx, @@ -423,7 +423,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>( } fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) { - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); + let access_levels = &tcx.privacy_access_levels(()); let krate = tcx.hir().krate(); @@ -448,6 +448,10 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) lint_callback!(cx, check_crate, krate); hir_visit::walk_crate(cx, krate); + for attr in krate.non_exported_macro_attrs { + // This HIR ID is a lie, since the macro ID isn't available. + cx.visit_attribute(hir::CRATE_HIR_ID, attr); + } lint_callback!(cx, check_crate_post, krate); }) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 54909381a10..91cdef9b089 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -6,8 +6,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::{intravisit, HirId}; +use rustc_hir::{intravisit, HirId, CRATE_HIR_ID}; use rustc_middle::hir::map::Map; use rustc_middle::lint::LevelAndSource; use rustc_middle::lint::LintDiagnosticBuilder; @@ -28,10 +27,9 @@ use tracing::debug; use std::cmp; -fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap { - assert_eq!(cnum, LOCAL_CRATE); +fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let store = unerased_lint_store(tcx); - let crate_attrs = tcx.get_attrs(DefId { krate: cnum, index: CRATE_DEF_INDEX }); + let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); let levels = LintLevelsBuilder::new(tcx.sess, false, &store, crate_attrs); let mut builder = LintLevelMapBuilder { levels, tcx, store }; let krate = tcx.hir().krate(); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index de5279c4a8d..b27eef376c4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -406,17 +406,17 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId { impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Span, String> { + let ctxt = SyntaxContext::decode(decoder)?; let tag = u8::decode(decoder)?; - if tag == TAG_INVALID_SPAN { - return Ok(DUMMY_SP); + if tag == TAG_PARTIAL_SPAN { + return Ok(DUMMY_SP.with_ctxt(ctxt)); } debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); let lo = BytePos::decode(decoder)?; let len = BytePos::decode(decoder)?; - let ctxt = SyntaxContext::decode(decoder)?; let hi = lo + len; let sess = if let Some(sess) = decoder.sess { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 82ca634f282..e25b22c8331 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -185,19 +185,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } foreign_modules => { cdata.get_foreign_modules(tcx) } - plugin_registrar_fn => { - cdata.root.plugin_registrar_fn.map(|index| { - DefId { krate: def_id.krate, index } - }) - } - proc_macro_decls_static => { - cdata.root.proc_macro_data.as_ref().map(|data| { - DefId { - krate: def_id.krate, - index: data.proc_macro_decls_static, - } - }) - } crate_disambiguator => { cdata.root.disambiguator } crate_hash => { cdata.root.hash } crate_host_hash => { cdata.host_hash } @@ -296,11 +283,10 @@ pub fn provide(providers: &mut Providers) { // external item that is visible from at least one local module) to a // sufficiently visible parent (considering modules that re-export the // external item to be parents). - visible_parent_map: |tcx, cnum| { + visible_parent_map: |tcx, ()| { use std::collections::hash_map::Entry; use std::collections::vec_deque::VecDeque; - assert_eq!(cnum, LOCAL_CRATE); let mut visible_parent_map: DefIdMap<DefId> = Default::default(); // Issue 46112: We want the map to prefer the shortest @@ -348,7 +334,7 @@ pub fn provide(providers: &mut Providers) { Entry::Occupied(mut entry) => { // If `child` is defined in crate `cnum`, ensure // that it is mapped to a parent in `cnum`. - if child.krate == cnum && entry.get().krate != cnum { + if child.is_local() && entry.get().is_local() { entry.insert(parent); } } @@ -370,17 +356,14 @@ pub fn provide(providers: &mut Providers) { visible_parent_map }, - dependency_formats: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - Lrc::new(crate::dependency_format::calculate(tcx)) - }, + dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)), has_global_allocator: |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); CStore::from_tcx(tcx).has_global_allocator() }, - postorder_cnums: |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(cnum)) + postorder_cnums: |tcx, ()| { + tcx.arena + .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, ..*providers diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 19c713665c7..0c31430598a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -187,11 +187,48 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId { impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { - if *self == rustc_span::DUMMY_SP { - return TAG_INVALID_SPAN.encode(s); + let span = self.data(); + + // Don't serialize any `SyntaxContext`s from a proc-macro crate, + // since we don't load proc-macro dependencies during serialization. + // This means that any hygiene information from macros used *within* + // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro + // definition) will be lost. + // + // This can show up in two ways: + // + // 1. Any hygiene information associated with identifier of + // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost. + // Since proc-macros can only be invoked from a different crate, + // real code should never need to care about this. + // + // 2. Using `Span::def_site` or `Span::mixed_site` will not + // include any hygiene information associated with the definition + // site. This means that a proc-macro cannot emit a `$crate` + // identifier which resolves to one of its dependencies, + // which also should never come up in practice. + // + // Additionally, this affects `Span::parent`, and any other + // span inspection APIs that would otherwise allow traversing + // the `SyntaxContexts` associated with a span. + // + // None of these user-visible effects should result in any + // cross-crate inconsistencies (getting one behavior in the same + // crate, and a different behavior in another crate) due to the + // limited surface that proc-macros can expose. + // + // IMPORTANT: If this is ever changed, be sure to update + // `rustc_span::hygiene::raw_encode_expn_id` to handle + // encoding `ExpnData` for proc-macro crates. + if s.is_proc_macro { + SyntaxContext::root().encode(s)?; + } else { + span.ctxt.encode(s)?; } - let span = self.data(); + if self.is_dummy() { + return TAG_PARTIAL_SPAN.encode(s); + } // The Span infrastructure should make sure that this invariant holds: debug_assert!(span.lo <= span.hi); @@ -206,7 +243,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { if !s.source_file_cache.0.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. - return TAG_INVALID_SPAN.encode(s); + return TAG_PARTIAL_SPAN.encode(s); } let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!"); @@ -262,43 +299,6 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span { let len = hi - lo; len.encode(s)?; - // Don't serialize any `SyntaxContext`s from a proc-macro crate, - // since we don't load proc-macro dependencies during serialization. - // This means that any hygiene information from macros used *within* - // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro - // definition) will be lost. - // - // This can show up in two ways: - // - // 1. Any hygiene information associated with identifier of - // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost. - // Since proc-macros can only be invoked from a different crate, - // real code should never need to care about this. - // - // 2. Using `Span::def_site` or `Span::mixed_site` will not - // include any hygiene information associated with the definition - // site. This means that a proc-macro cannot emit a `$crate` - // identifier which resolves to one of its dependencies, - // which also should never come up in practice. - // - // Additionally, this affects `Span::parent`, and any other - // span inspection APIs that would otherwise allow traversing - // the `SyntaxContexts` associated with a span. - // - // None of these user-visible effects should result in any - // cross-crate inconsistencies (getting one behavior in the same - // crate, and a different behavior in another crate) due to the - // limited surface that proc-macros can expose. - // - // IMPORTANT: If this is ever changed, be sure to update - // `rustc_span::hygiene::raw_encode_expn_id` to handle - // encoding `ExpnData` for proc-macro crates. - if s.is_proc_macro { - SyntaxContext::root().encode(s)?; - } else { - span.ctxt.encode(s)?; - } - if tag == TAG_VALID_SPAN_FOREIGN { // This needs to be two lines to avoid holding the `s.source_file_cache` // while calling `cnum.encode(s)` @@ -678,7 +678,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), has_default_lib_allocator, - plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index), proc_macro_data, compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins), needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator), @@ -970,13 +969,12 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id)); } } - let inherent_impls = tcx.crate_inherent_impls(LOCAL_CRATE); + let inherent_impls = tcx.crate_inherent_impls(()); for (def_id, implementations) in inherent_impls.inherent_impls.iter() { - assert!(def_id.is_local()); if implementations.is_empty() { continue; } - record!(self.tables.inherent_impls[def_id] <- implementations.iter().map(|&def_id| { + record!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })); @@ -1263,7 +1261,7 @@ impl EncodeContext<'a, 'tcx> { let mut keys_and_jobs = self .tcx - .mir_keys(LOCAL_CRATE) + .mir_keys(()) .iter() .filter_map(|&def_id| { let (encode_const, encode_opt) = should_encode_mir(self.tcx, def_id); @@ -1601,7 +1599,7 @@ impl EncodeContext<'a, 'tcx> { let tcx = self.tcx; let hir = tcx.hir(); - let proc_macro_decls_static = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap().index; + let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index; let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied(); let macros = self.lazy(hir.krate().proc_macros.iter().map(|p| p.owner.local_def_index)); let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); @@ -1798,7 +1796,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> { empty_proc_macro!(self); - let formats = self.tcx.dependency_formats(LOCAL_CRATE); + let formats = self.tcx.dependency_formats(()); for (ty, arr) in formats.iter() { if *ty != CrateType::Dylib { continue; @@ -2028,7 +2026,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { return; } - par_iter(tcx.mir_keys(LOCAL_CRATE)).for_each(|&def_id| { + par_iter(tcx.mir_keys(())).for_each(|&def_id| { let (encode_const, encode_opt) = should_encode_mir(tcx, def_id); if encode_const { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 6b375045f14..04fe5cf5890 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -209,7 +209,6 @@ crate struct CrateRoot<'tcx> { has_global_allocator: bool, has_panic_handler: bool, has_default_lib_allocator: bool, - plugin_registrar_fn: Option<DefIndex>, crate_deps: Lazy<[CrateDep]>, dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>, @@ -451,4 +450,4 @@ struct GeneratorData<'tcx> { // Tags used for encoding Spans: const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; -const TAG_INVALID_SPAN: u8 = 2; +const TAG_PARTIAL_SPAN: u8 = 2; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 09736c6f1e5..d154b7804f0 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -150,7 +150,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> { impl<'hir> Map<'hir> { pub fn krate(&self) -> &'hir Crate<'hir> { - self.tcx.hir_crate(LOCAL_CRATE) + self.tcx.hir_crate(()) } #[inline] @@ -489,7 +489,7 @@ impl<'hir> Map<'hir> { } pub fn trait_impls(&self, trait_did: DefId) -> &'hir [LocalDefId] { - self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..]) + self.tcx.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) } /// Gets the attributes on the crate. This is preferable to @@ -928,9 +928,7 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> { - assert_eq!(cnum, LOCAL_CRATE); - +pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tcx> { let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); let hcx = tcx.create_stable_hashing_context(); @@ -943,10 +941,12 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe } pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { + assert_eq!(crate_num, LOCAL_CRATE); + let mut hcx = tcx.create_stable_hashing_context(); let mut hir_body_nodes: Vec<_> = tcx - .index_hir(crate_num) + .index_hir(()) .map .iter_enumerated() .filter_map(|(def_id, hod)| { diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 565664778e5..879372c65ea 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -13,7 +13,7 @@ use rustc_ast::Attribute; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::*; use rustc_index::vec::IndexVec; use rustc_span::DUMMY_SP; @@ -123,14 +123,14 @@ pub fn provide(providers: &mut Providers) { let hir = tcx.hir(); hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))) }; - providers.hir_crate = |tcx, _| tcx.untracked_crate; + providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.index_hir = map::index_hir; providers.crate_hash = map::crate_hash; providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id]; - providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature; - providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref(); + providers.hir_owner = |tcx, id| tcx.index_hir(()).map[id].signature; + providers.hir_owner_nodes = |tcx, id| tcx.index_hir(()).map[id].with_bodies.as_deref(); providers.hir_owner_parent = |tcx, id| { - let index = tcx.index_hir(LOCAL_CRATE); + let index = tcx.index_hir(()); index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID) }; providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id }; @@ -151,4 +151,5 @@ pub fn provide(providers: &mut Providers) { } }; providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local()); + providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls; } diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 641cf23781e..0b05dd5c0ba 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -16,37 +16,48 @@ pub trait ToType { } #[derive(PartialEq, Copy, Clone, Debug)] -pub struct RegionVidKey { - /// The minimum region vid in the unification set. This is needed - /// to have a canonical name for a type to prevent infinite - /// recursion. - pub min_vid: ty::RegionVid, -} - -impl UnifyValue for RegionVidKey { - type Error = NoError; +pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>); - fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> { - let min_vid = if value1.min_vid.index() < value2.min_vid.index() { - value1.min_vid - } else { - value2.min_vid - }; +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct RegionVidKey<'tcx> { + pub vid: ty::RegionVid, + pub phantom: PhantomData<UnifiedRegion<'tcx>>, +} - Ok(RegionVidKey { min_vid }) +impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> { + fn from(vid: ty::RegionVid) -> Self { + RegionVidKey { vid, phantom: PhantomData } } } -impl UnifyKey for ty::RegionVid { - type Value = RegionVidKey; +impl<'tcx> UnifyKey for RegionVidKey<'tcx> { + type Value = UnifiedRegion<'tcx>; fn index(&self) -> u32 { - u32::from(*self) + self.vid.as_u32() } - fn from_index(i: u32) -> ty::RegionVid { - ty::RegionVid::from(i) + fn from_index(i: u32) -> Self { + RegionVidKey::from(ty::RegionVid::from_u32(i)) } fn tag() -> &'static str { - "RegionVid" + "RegionVidKey" + } +} + +impl<'tcx> UnifyValue for UnifiedRegion<'tcx> { + type Error = NoError; + + fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> { + Ok(match (value1.0, value2.0) { + // Here we can just pick one value, because the full constraints graph + // will be handled later. Ideally, we might want a `MultipleValues` + // variant or something. For now though, this is fine. + (Some(_), Some(_)) => *value1, + + (Some(_), _) => *value1, + (_, Some(_)) => *value2, + + (None, None) => *value1, + }) } } diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index 82b9ebcc7ec..d63116e29c8 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -251,7 +251,7 @@ pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, Some((cnum, path)) }) .collect::<Vec<_>>(); - let mut ordering = tcx.postorder_cnums(LOCAL_CRATE).to_owned(); + let mut ordering = tcx.postorder_cnums(()).to_owned(); ordering.reverse(); libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a)); libs diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 766d6a06f7e..929818bd1ee 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -27,8 +27,6 @@ pub struct Allocation<Tag = (), Extra = ()> { relocations: Relocations<Tag>, /// Denotes which part of this allocation is initialized. init_mask: InitMask, - /// The size of the allocation. Currently, must always equal `bytes.len()`. - pub size: Size, /// The alignment of the allocation to detect unaligned reads. /// (`Align` guarantees that this is a power of two.) pub align: Align, @@ -94,7 +92,6 @@ impl<Tag> Allocation<Tag> { bytes, relocations: Relocations::new(), init_mask: InitMask::new(size, true), - size, align, mutability: Mutability::Not, extra: (), @@ -110,7 +107,6 @@ impl<Tag> Allocation<Tag> { bytes: vec![0; size.bytes_usize()], relocations: Relocations::new(), init_mask: InitMask::new(size, false), - size, align, mutability: Mutability::Mut, extra: (), @@ -127,7 +123,6 @@ impl Allocation<(), ()> { ) -> Allocation<T, E> { Allocation { bytes: self.bytes, - size: self.size, relocations: Relocations::from_presorted( self.relocations .iter() @@ -150,7 +145,11 @@ impl Allocation<(), ()> { /// Raw accessors. Provide access to otherwise private bytes. impl<Tag, Extra> Allocation<Tag, Extra> { pub fn len(&self) -> usize { - self.size.bytes_usize() + self.bytes.len() + } + + pub fn size(&self) -> Size { + Size::from_bytes(self.len()) } /// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs @@ -276,29 +275,6 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { /// Reading and writing. impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { - /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached - /// before a `0` is found. - /// - /// Most likely, you want to call `Memory::read_c_str` instead of this method. - pub fn read_c_str( - &self, - cx: &impl HasDataLayout, - ptr: Pointer<Tag>, - ) -> InterpResult<'tcx, &[u8]> { - let offset = ptr.offset.bytes_usize(); - Ok(match self.bytes[offset..].iter().position(|&c| c == 0) { - Some(size) => { - let size_with_null = Size::from_bytes(size) + Size::from_bytes(1); - // Go through `get_bytes` for checks and AllocationExtra hooks. - // We read the null, so we include it in the request, but we want it removed - // from the result, so we do subslicing. - &self.get_bytes(cx, ptr, size_with_null)?[..size] - } - // This includes the case where `offset` is out-of-bounds to begin with. - None => throw_ub!(UnterminatedCString(ptr.erase_tag())), - }) - } - /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a /// relocation. If `allow_uninit_and_ptr` is `false`, also enforces that the memory in the /// given range contains neither relocations nor uninitialized bytes. diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 67440e6e0ed..edf2e539765 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -88,7 +88,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(ref instance) => { - let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id); + let entry_def_id = tcx.entry_fn(()).map(|(id, _)| id); // If this function isn't inlined or otherwise has an extern // indicator, then we'll be creating a globally shared version. if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator() diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index a80aa6ad3d8..0edb79fdbc8 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -32,7 +32,6 @@ pub enum UnsafetyViolationDetails { UseOfInlineAssembly, InitializingTypeWith, CastOfPointerToInt, - BorrowOfPackedField, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, @@ -64,11 +63,6 @@ impl UnsafetyViolationDetails { CastOfPointerToInt => { ("cast of pointer to int", "casting pointers to integers in constants") } - BorrowOfPackedField => ( - "borrow of packed field", - "fields of packed structs might be misaligned: dereferencing a misaligned pointer \ - or even just creating a misaligned reference is undefined behavior", - ), UseOfMutableStatic => ( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing violations or data \ diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index fea2aec38a1..70f70788bca 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -20,7 +20,7 @@ rustc_queries! { /// This is because the `hir_crate` query gives you access to all other items. /// To avoid this fate, do not call `tcx.hir().krate()`; instead, /// prefer wrappers like `tcx.visit_all_items_in_krate()`. - query hir_crate(key: CrateNum) -> &'tcx Crate<'tcx> { + query hir_crate(key: ()) -> &'tcx Crate<'tcx> { eval_always no_hash desc { "get the crate HIR" } @@ -28,7 +28,7 @@ rustc_queries! { /// The indexed HIR. This can be conveniently accessed by `tcx.hir()`. /// Avoid calling this query directly. - query index_hir(_: CrateNum) -> &'tcx crate::hir::IndexedHir<'tcx> { + query index_hir(_: ()) -> &'tcx crate::hir::IndexedHir<'tcx> { eval_always no_hash desc { "index HIR" } @@ -114,7 +114,7 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - query analysis(key: CrateNum) -> Result<(), ErrorReported> { + query analysis(key: ()) -> Result<(), ErrorReported> { eval_always desc { "running analysis passes on this crate" } } @@ -199,7 +199,7 @@ rustc_queries! { desc { "looking up the native libraries of a linked crate" } } - query lint_levels(_: CrateNum) -> LintLevelMap { + query lint_levels(_: ()) -> LintLevelMap { storage(ArenaCacheSelector<'tcx>) eval_always desc { "computing the lint levels for items in this crate" } @@ -223,7 +223,7 @@ rustc_queries! { /// Set of all the `DefId`s in this crate that have MIR associated with /// them. This includes all the body owners, but also things like struct /// constructors. - query mir_keys(_: CrateNum) -> FxHashSet<LocalDefId> { + query mir_keys(_: ()) -> FxHashSet<LocalDefId> { storage(ArenaCacheSelector<'tcx>) desc { "getting a list of all mir_keys" } } @@ -335,10 +335,9 @@ rustc_queries! { /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` /// MIR pass (assuming the -Zinstrument-coverage option is enabled). - query coverageinfo(key: DefId) -> mir::CoverageInfo { - desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key) } + query coverageinfo(key: ty::InstanceDef<'tcx>) -> mir::CoverageInfo { + desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) } storage(ArenaCacheSelector<'tcx>) - cache_on_disk_if { key.is_local() } } /// Returns the name of the file that contains the function body, if instrumented for coverage. @@ -544,7 +543,7 @@ rustc_queries! { } /// Gets a map with the variance of every item; use `item_variance` instead. - query crate_variances(_: CrateNum) -> ty::CrateVariancesMap<'tcx> { + query crate_variances(_: ()) -> ty::CrateVariancesMap<'tcx> { storage(ArenaCacheSelector<'tcx>) desc { "computing the variances for items in this crate" } } @@ -555,8 +554,7 @@ rustc_queries! { } /// Maps from thee `DefId` of a type to its (inferred) outlives. - query inferred_outlives_crate(_: CrateNum) - -> ty::CratePredicatesMap<'tcx> { + query inferred_outlives_crate(_: ()) -> ty::CratePredicatesMap<'tcx> { storage(ArenaCacheSelector<'tcx>) desc { "computing the inferred outlives predicates for items in this crate" } } @@ -695,7 +693,7 @@ rustc_queries! { desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } } - query typeck_item_bodies(_: CrateNum) -> () { + query typeck_item_bodies(_: ()) -> () { desc { "type-checking all item bodies" } } @@ -754,18 +752,15 @@ rustc_queries! { /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. - /// (Defined only for `LOCAL_CRATE`.) - query crate_inherent_impls(k: CrateNum) - -> CrateInherentImpls { + query crate_inherent_impls(k: ()) -> CrateInherentImpls { storage(ArenaCacheSelector<'tcx>) eval_always - desc { "all inherent impls defined in crate `{:?}`", k } + desc { "all inherent impls defined in crate" } } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. /// Not meant to be used directly outside of coherence. - /// (Defined only for `LOCAL_CRATE`.) - query crate_inherent_impls_overlap_check(_: CrateNum) + query crate_inherent_impls_overlap_check(_: ()) -> () { eval_always desc { "check for overlap between inherent impls defined in this crate" } @@ -859,16 +854,16 @@ rustc_queries! { } /// Performs part of the privacy check and computes "access levels". - query privacy_access_levels(_: CrateNum) -> &'tcx AccessLevels { + query privacy_access_levels(_: ()) -> &'tcx AccessLevels { eval_always desc { "privacy access levels" } } - query check_private_in_public(_: CrateNum) -> () { + query check_private_in_public(_: ()) -> () { eval_always desc { "checking for private elements in public interfaces" } } - query reachable_set(_: CrateNum) -> FxHashSet<LocalDefId> { + query reachable_set(_: ()) -> FxHashSet<LocalDefId> { storage(ArenaCacheSelector<'tcx>) desc { "reachability" } } @@ -978,7 +973,7 @@ rustc_queries! { /// Passing in any other crate will cause an ICE. /// /// [`LOCAL_CRATE`]: rustc_hir::def_id::LOCAL_CRATE - query all_local_trait_impls(local_crate: CrateNum) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> { + query all_local_trait_impls(_: ()) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> { desc { "local trait impls" } } @@ -1035,6 +1030,10 @@ rustc_queries! { query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } } + /// Query backing `TyS::has_significant_drop_raw`. + query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` has a significant drop", env.value } + } /// Query backing `TyS::is_structural_eq_shallow`. /// @@ -1055,6 +1054,17 @@ rustc_queries! { cache_on_disk_if { true } } + /// A list of types where the ADT requires drop if and only if any of those types + /// has significant drop. A type marked with the attribute `rustc_insignificant_dtor` + /// is considered to not be significant. A drop is significant if it is implemented + /// by the user or does anything that will have any observable behavior (other than + /// freeing up memory). If the ADT is known to have a significant destructor then + /// `Err(AlwaysRequiresDrop)` is returned. + query adt_significant_drop_tys(def_id: DefId) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> { + desc { |tcx| "computing when `{}` has a significant destructor", tcx.def_path_str(def_id) } + cache_on_disk_if { false } + } + query layout_raw( env: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result<&'tcx rustc_target::abi::Layout, ty::layout::LayoutError<'tcx>> { @@ -1066,9 +1076,7 @@ rustc_queries! { desc { "dylib dependency formats of crate" } } - query dependency_formats(_: CrateNum) - -> Lrc<crate::middle::dependency_format::Dependencies> - { + query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> { desc { "get the linkage format of all dependencies" } } @@ -1156,10 +1164,10 @@ rustc_queries! { query is_reachable_non_generic(def_id: DefId) -> bool { desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } } - query is_unreachable_local_definition(def_id: DefId) -> bool { + query is_unreachable_local_definition(def_id: LocalDefId) -> bool { desc { |tcx| "checking whether `{}` is reachable from outside the crate", - tcx.def_path_str(def_id), + tcx.def_path_str(def_id.to_def_id()), } } @@ -1169,11 +1177,9 @@ rustc_queries! { /// added or removed in any upstream crate. Instead use the narrower /// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even /// better, `Instance::upstream_monomorphization()`. - query upstream_monomorphizations( - k: CrateNum - ) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> { + query upstream_monomorphizations(_: ()) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> { storage(ArenaCacheSelector<'tcx>) - desc { "collecting available upstream monomorphizations `{:?}`", k } + desc { "collecting available upstream monomorphizations" } } /// Returns the set of upstream monomorphizations available for the @@ -1216,13 +1222,13 @@ rustc_queries! { /// Identifies the entry-point (e.g., the `main` function) for a given /// crate, returning `None` if there is no entry point (such as for library crates). - query entry_fn(_: CrateNum) -> Option<(DefId, EntryFnType)> { + query entry_fn(_: ()) -> Option<(DefId, EntryFnType)> { desc { "looking up the entry function of a crate" } } - query plugin_registrar_fn(_: CrateNum) -> Option<DefId> { + query plugin_registrar_fn(_: ()) -> Option<LocalDefId> { desc { "looking up the plugin registrar for a crate" } } - query proc_macro_decls_static(_: CrateNum) -> Option<DefId> { + query proc_macro_decls_static(_: ()) -> Option<LocalDefId> { desc { "looking up the derive registrar for a crate" } } query crate_disambiguator(_: CrateNum) -> CrateDisambiguator { @@ -1349,7 +1355,7 @@ rustc_queries! { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } - query get_lib_features(_: CrateNum) -> LibFeatures { + query get_lib_features(_: ()) -> LibFeatures { storage(ArenaCacheSelector<'tcx>) eval_always desc { "calculating the lib features map" } @@ -1359,16 +1365,14 @@ rustc_queries! { desc { "calculating the lib features defined in a crate" } } /// Returns the lang items defined in another crate by loading it from metadata. - // FIXME: It is illegal to pass a `CrateNum` other than `LOCAL_CRATE` here, just get rid - // of that argument? - query get_lang_items(_: CrateNum) -> LanguageItems { + query get_lang_items(_: ()) -> LanguageItems { storage(ArenaCacheSelector<'tcx>) eval_always desc { "calculating the lang items map" } } /// Returns all diagnostic items defined in all crates. - query all_diagnostic_items(_: CrateNum) -> FxHashMap<Symbol, DefId> { + query all_diagnostic_items(_: ()) -> FxHashMap<Symbol, DefId> { storage(ArenaCacheSelector<'tcx>) eval_always desc { "calculating the diagnostic items map" } @@ -1388,13 +1392,11 @@ rustc_queries! { query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { desc { "calculating the missing lang items in a crate" } } - query visible_parent_map(_: CrateNum) - -> DefIdMap<DefId> { + query visible_parent_map(_: ()) -> DefIdMap<DefId> { storage(ArenaCacheSelector<'tcx>) desc { "calculating the visible parent map" } } - query trimmed_def_paths(_: CrateNum) - -> FxHashMap<DefId, Symbol> { + query trimmed_def_paths(_: ()) -> FxHashMap<DefId, Symbol> { storage(ArenaCacheSelector<'tcx>) desc { "calculating trimmed def paths" } } @@ -1406,7 +1408,7 @@ rustc_queries! { eval_always desc { "looking at the source for a crate" } } - query postorder_cnums(_: CrateNum) -> &'tcx [CrateNum] { + query postorder_cnums(_: ()) -> &'tcx [CrateNum] { eval_always desc { "generating a postorder list of CrateNums" } } @@ -1419,8 +1421,7 @@ rustc_queries! { eval_always desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) } } - query maybe_unused_extern_crates(_: CrateNum) - -> &'tcx [(LocalDefId, Span)] { + query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] { eval_always desc { "looking up all possibly unused extern crates" } } @@ -1430,12 +1431,12 @@ rustc_queries! { desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) } } - query stability_index(_: CrateNum) -> stability::Index<'tcx> { + query stability_index(_: ()) -> stability::Index<'tcx> { storage(ArenaCacheSelector<'tcx>) eval_always desc { "calculating the stability index for the local crate" } } - query all_crate_nums(_: CrateNum) -> &'tcx [CrateNum] { + query all_crate_nums(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } } @@ -1443,7 +1444,7 @@ rustc_queries! { /// A vector of every trait accessible in the whole crate /// (i.e., including those from subcrates). This is used only for /// error reporting. - query all_traits(_: CrateNum) -> &'tcx [DefId] { + query all_traits(_: ()) -> &'tcx [DefId] { desc { "fetching all foreign and local traits" } } @@ -1457,8 +1458,7 @@ rustc_queries! { desc { "exported_symbols" } } - query collect_and_partition_mono_items(_: CrateNum) - -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { + query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { eval_always desc { "collect_and_partition_mono_items" } } @@ -1467,8 +1467,7 @@ rustc_queries! { } /// All items participating in code generation together with items inlined into them. - query codegened_and_inlined_items(_: CrateNum) - -> &'tcx DefIdSet { + query codegened_and_inlined_items(_: ()) -> &'tcx DefIdSet { eval_always desc { "codegened_and_inlined_items" } } @@ -1483,11 +1482,11 @@ rustc_queries! { tcx.def_path_str(key) } } - query backend_optimization_level(_: CrateNum) -> OptLevel { + query backend_optimization_level(_: ()) -> OptLevel { desc { "optimization level used by backend" } } - query output_filenames(_: CrateNum) -> Arc<OutputFilenames> { + query output_filenames(_: ()) -> Arc<OutputFilenames> { eval_always desc { "output_filenames" } } @@ -1663,7 +1662,7 @@ rustc_queries! { desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) } } - query features_query(_: CrateNum) -> &'tcx rustc_feature::Features { + query features_query(_: ()) -> &'tcx rustc_feature::Features { eval_always desc { "looking up enabled feature gates" } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7c4229b6db2..dde5cbadbd9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1218,18 +1218,18 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures { - self.get_lib_features(LOCAL_CRATE) + self.get_lib_features(()) } /// Obtain all lang items of this crate and all dependencies (recursively) pub fn lang_items(self) -> &'tcx rustc_hir::lang_items::LanguageItems { - self.get_lang_items(LOCAL_CRATE) + self.get_lang_items(()) } /// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to /// compare against another `DefId`, since `is_diagnostic_item` is cheaper. pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> { - self.all_diagnostic_items(LOCAL_CRATE).get(&name).copied() + self.all_diagnostic_items(()).get(&name).copied() } /// Check whether the diagnostic item with the given `name` has the given `DefId`. @@ -1238,11 +1238,11 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn stability(self) -> &'tcx stability::Index<'tcx> { - self.stability_index(LOCAL_CRATE) + self.stability_index(()) } pub fn crates(self) -> &'tcx [CrateNum] { - self.all_crate_nums(LOCAL_CRATE) + self.all_crate_nums(()) } pub fn allocator_kind(self) -> Option<AllocatorKind> { @@ -1250,7 +1250,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn features(self) -> &'tcx rustc_feature::Features { - self.features_query(LOCAL_CRATE) + self.features_query(()) } pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey { @@ -2623,7 +2623,7 @@ impl<'tcx> TyCtxt<'tcx> { lint: &'static Lint, mut id: hir::HirId, ) -> (Level, LintLevelSource) { - let sets = self.lint_levels(LOCAL_CRATE); + let sets = self.lint_levels(()); loop { if let Some(pair) = sets.level_and_source(lint, id, self.sess) { return pair; @@ -2795,10 +2795,7 @@ pub fn provide(providers: &mut ty::query::Providers) { tcx.crate_name }; providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id); - providers.maybe_unused_extern_crates = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - &tcx.maybe_unused_extern_crates[..] - }; + providers.maybe_unused_extern_crates = |tcx, ()| &tcx.maybe_unused_extern_crates[..]; providers.names_imported_by_glob_use = |tcx, id| tcx.arena.alloc(tcx.glob_map.get(&id).cloned().unwrap_or_default()); @@ -2815,18 +2812,9 @@ pub fn provide(providers: &mut ty::query::Providers) { tcx.stability().local_deprecation_entry(id) }; providers.extern_mod_stmt_cnum = |tcx, id| tcx.extern_crate_map.get(&id).cloned(); - providers.all_crate_nums = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.arena.alloc_slice(&tcx.cstore.crates_untracked()) - }; - providers.output_filenames = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.output_filenames.clone() - }; - providers.features_query = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.sess.features_untracked() - }; + providers.all_crate_nums = |tcx, ()| tcx.arena.alloc_slice(&tcx.cstore.crates_untracked()); + providers.output_filenames = |tcx, ()| tcx.output_filenames.clone(); + providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index af49533753f..94e325e9e87 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -36,7 +36,7 @@ use rustc_data_structures::sync::{self, par_iter, ParallelIterator}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX}; use rustc_hir::{Constness, Node}; use rustc_macros::HashStable; use rustc_span::hygiene::ExpnId; @@ -1970,7 +1970,6 @@ pub fn provide(providers: &mut ty::query::Providers) { super::util::bug::provide(providers); *providers = ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, - all_local_trait_impls: trait_def::all_local_trait_impls, type_uninhabited_from: inhabitedness::type_uninhabited_from, const_param_default: consts::const_param_default, ..*providers @@ -1984,7 +1983,7 @@ pub fn provide(providers: &mut ty::query::Providers) { /// (constructing this map requires touching the entire crate). #[derive(Clone, Debug, Default, HashStable)] pub struct CrateInherentImpls { - pub inherent_impls: DefIdMap<Vec<DefId>>, + pub inherent_impls: LocalDefIdMap<Vec<DefId>>, } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index cfb9cfd86f9..76c48597092 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::ItemKind; use rustc_session::config::TrimmedDefPaths; @@ -285,7 +285,7 @@ pub trait PrettyPrinter<'tcx>: return Ok((self, false)); } - match self.tcx().trimmed_def_paths(LOCAL_CRATE).get(&def_id) { + match self.tcx().trimmed_def_paths(()).get(&def_id) { None => Ok((self, false)), Some(symbol) => { self.write_str(&symbol.as_str())?; @@ -361,7 +361,7 @@ pub trait PrettyPrinter<'tcx>: return Ok((self, false)); } - let visible_parent_map = self.tcx().visible_parent_map(LOCAL_CRATE); + let visible_parent_map = self.tcx().visible_parent_map(()); let mut cur_def_key = self.tcx().def_key(def_id); debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); @@ -2302,9 +2302,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere. /// /// The implementation uses similar import discovery logic to that of 'use' suggestions. -fn trimmed_def_paths(tcx: TyCtxt<'_>, crate_num: CrateNum) -> FxHashMap<DefId, Symbol> { - assert_eq!(crate_num, LOCAL_CRATE); - +fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> { let mut map = FxHashMap::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index f220d83b0c7..a688b816e9a 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -579,7 +579,7 @@ impl<'sess> OnDiskCache<'sess> { ) -> IndexVec<CrateNum, Option<CrateNum>> { tcx.dep_graph.with_ignore(|| { let current_cnums = tcx - .all_crate_nums(LOCAL_CRATE) + .all_crate_nums(()) .iter() .map(|&cnum| { let crate_name = tcx.original_crate_name(cnum).to_string(); diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index e9b8883f29a..79166472acf 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -4,14 +4,13 @@ use crate::ty::fast_reject; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_macros::HashStable; -use std::collections::BTreeMap; /// A trait's definition with type information. #[derive(HashStable)] @@ -209,14 +208,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -// Query provider for `all_local_trait_impls`. -pub(super) fn all_local_trait_impls<'tcx>( - tcx: TyCtxt<'tcx>, - krate: CrateNum, -) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> { - &tcx.hir_crate(krate).trait_impls -} - // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls { let mut impls = TraitImpls::default(); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e365928c15f..7bf69b9e637 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -791,6 +791,39 @@ impl<'tcx> ty::TyS<'tcx> { } } + /// Checks if `ty` has has a significant drop. + /// + /// Note that this method can return false even if `ty` has a destructor + /// attached; even if that is the case then the adt has been marked with + /// the attribute `rustc_insignificant_dtor`. + /// + /// Note that this method is used to check for change in drop order for + /// 2229 drop reorder migration analysis. + #[inline] + pub fn has_significant_drop( + &'tcx self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + // Avoid querying in simple cases. + match needs_drop_components(self, &tcx.data_layout) { + Err(AlwaysRequiresDrop) => true, + Ok(components) => { + let query_ty = match *components { + [] => return false, + // If we've got a single component, call the query with that + // to increase the chance that we hit the query cache. + [component_ty] => component_ty, + _ => self, + }; + // This doesn't depend on regions, so try to minimize distinct + // query keys used. + let erased = tcx.normalize_erasing_regions(param_env, query_ty); + tcx.has_significant_drop_raw(param_env.and(erased)) + } + } + } + /// Returns `true` if equality for this type is both reflexive and structural. /// /// Reflexive equality for a type is indicated by an `Eq` impl for that type. diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs index bbd512fd360..f4d78ac04cb 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs @@ -1241,7 +1241,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// it. However, it works pretty well in practice. In particular, /// this is needed to deal with projection outlives bounds like /// - /// ```ignore (internal compiler representation so lifetime syntax is invalid) + /// ```text /// <T as Foo<'0>>::Item: '1 /// ``` /// diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index 994b403abf3..1bfbb843114 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -137,10 +137,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.loc, InteriorOfSliceOrArray { ty: place_ty, - is_index: match elem { - ProjectionElem::Index(..) => true, - _ => false, - }, + is_index: matches!(elem, ProjectionElem::Index(..)), }, )); } diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index 1aaa56403f4..5200e4aa90d 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -244,7 +244,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let new_ptr = self.allocate(new_size, new_align, kind); let old_size = match old_size_and_align { Some((size, _align)) => size, - None => self.get_raw(ptr.alloc_id)?.size, + None => self.get_raw(ptr.alloc_id)?.size(), }; self.copy(ptr, new_ptr, old_size.min(new_size), /*nonoverlapping*/ true)?; self.deallocate(ptr, old_size_and_align, kind)?; @@ -306,11 +306,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ); } if let Some((size, align)) = old_size_and_align { - if size != alloc.size || align != alloc.align { + if size != alloc.size() || align != alloc.align { throw_ub_format!( "incorrect layout on deallocation: {} has size {} and alignment {}, but gave size {} and alignment {}", ptr.alloc_id, - alloc.size.bytes(), + alloc.size().bytes(), alloc.align.bytes(), size.bytes(), align.bytes(), @@ -319,11 +319,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } // Let the machine take some extra action - let size = alloc.size; + let size = alloc.size(); AllocationExtra::memory_deallocated(&mut alloc, ptr, size)?; // Don't forget to remember size and align of this now-dead allocation - let old = self.dead_alloc_map.insert(ptr.alloc_id, (alloc.size, alloc.align)); + let old = self.dead_alloc_map.insert(ptr.alloc_id, (alloc.size(), alloc.align)); if old.is_some() { bug!("Nothing can be deallocated twice"); } @@ -586,7 +586,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // a) cause cycles in case `id` refers to a static // b) duplicate a global's allocation in miri if let Some((_, alloc)) = self.alloc_map.get(id) { - return Ok((alloc.size, alloc.align)); + return Ok((alloc.size(), alloc.align)); } // # Function pointers @@ -614,7 +614,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(GlobalAlloc::Memory(alloc)) => { // Need to duplicate the logic here, because the global allocations have // different associated types than the interpreter-local ones. - Ok((alloc.size, alloc.align)) + Ok((alloc.size(), alloc.align)) } Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"), // The rest must be dead. @@ -804,41 +804,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.get_raw(ptr.alloc_id)?.get_bytes(self, ptr, size) } - /// Reads a 0-terminated sequence of bytes from memory. Returns them as a slice. - /// - /// Performs appropriate bounds checks. - pub fn read_c_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, &[u8]> { - let ptr = self.force_ptr(ptr)?; // We need to read at least 1 byte, so we *need* a ptr. - self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr) - } - - /// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec<u16>. - /// Terminator 0x0000 is not included in the returned Vec<u16>. - /// - /// Performs appropriate bounds checks. - pub fn read_wide_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, Vec<u16>> { - let size_2bytes = Size::from_bytes(2); - let align_2bytes = Align::from_bytes(2).unwrap(); - // We need to read at least 2 bytes, so we *need* a ptr. - let mut ptr = self.force_ptr(ptr)?; - let allocation = self.get_raw(ptr.alloc_id)?; - let mut u16_seq = Vec::new(); - - loop { - ptr = self - .check_ptr_access(ptr.into(), size_2bytes, align_2bytes)? - .expect("cannot be a ZST"); - let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?; - if single_u16 != 0x0000 { - u16_seq.push(single_u16); - ptr = ptr.offset(size_2bytes, self)?; - } else { - break; - } - } - Ok(u16_seq) - } - /// Writes the given stream of bytes into memory. /// /// Performs appropriate bounds checks. @@ -866,46 +831,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src) } - /// Writes the given stream of u16s into memory. - /// - /// Performs appropriate bounds checks. - pub fn write_u16s( - &mut self, - ptr: Scalar<M::PointerTag>, - src: impl IntoIterator<Item = u16>, - ) -> InterpResult<'tcx> { - let mut src = src.into_iter(); - let (lower, upper) = src.size_hint(); - let len = upper.expect("can only write bounded iterators"); - assert_eq!(lower, len, "can only write iterators with a precise length"); - - let size = Size::from_bytes(lower); - let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(2).unwrap())? { - Some(ptr) => ptr, - None => { - // zero-sized access - assert_matches!( - src.next(), - None, - "iterator said it was empty but returned an element" - ); - return Ok(()); - } - }; - let tcx = self.tcx; - let allocation = self.get_raw_mut(ptr.alloc_id)?; - - for idx in 0..len { - let val = Scalar::from_u16( - src.next().expect("iterator was shorter than it said it would be"), - ); - let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication - allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?; - } - assert_matches!(src.next(), None, "iterator was longer than it said it would be"); - Ok(()) - } - /// Expects the caller to have checked bounds and alignment. pub fn copy( &mut self, diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs index 4aa1360d535..a7fcb41f74a 100644 --- a/compiler/rustc_mir/src/interpret/terminator.rs +++ b/compiler/rustc_mir/src/interpret/terminator.rs @@ -3,7 +3,10 @@ use std::convert::TryFrom; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::Instance; -use rustc_middle::{mir, ty}; +use rustc_middle::{ + mir, + ty::{self, Ty}, +}; use rustc_target::abi::{self, LayoutOf as _}; use rustc_target::spec::abi::Abi; @@ -228,15 +231,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // ABI check - { - let callee_abi = { - let instance_ty = instance.ty(*self.tcx, self.param_env); - match instance_ty.kind() { - ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::Generator(..) => Abi::Rust, - _ => span_bug!(self.cur_span(), "unexpected callee ty: {:?}", instance_ty), - } + let check_abi = |this: &Self, instance_ty: Ty<'tcx>| -> InterpResult<'tcx> { + let callee_abi = match instance_ty.kind() { + ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Generator(..) => Abi::Rust, + _ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty), }; let normalize_abi = |abi| match abi { Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic => @@ -253,10 +253,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { caller_abi.name() ) } - } + Ok(()) + }; match instance.def { ty::InstanceDef::Intrinsic(..) => { + check_abi(self, instance.ty(*self.tcx, self.param_env))?; assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic); M::call_intrinsic(self, instance, args, ret, unwind) } @@ -274,6 +276,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { None => return Ok(()), }; + // Check against the ABI of the MIR body we are calling (not the ABI of `instance`; + // these can differ when `find_mir_or_eval_fn` does something clever like resolve + // exported symbol names). + check_abi(self, self.tcx.type_of(body.source.def_id()))?; + self.push_stack_frame( instance, body, diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs index 6e6e64d25ac..83b0d0528f7 100644 --- a/compiler/rustc_mir/src/interpret/validity.rs +++ b/compiler/rustc_mir/src/interpret/validity.rs @@ -833,6 +833,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)), self.path, err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" }, + err_unsup!(ReadPointerAsBytes) => { "a pointer in `str`" }, ); } ty::Array(tys, ..) | ty::Slice(tys) diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index e4ad92eb1b1..ef79f36b3b5 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -184,7 +184,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; use rustc_errors::{ErrorReported, FatalError}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; @@ -322,7 +322,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem< let mut roots = Vec::new(); { - let entry_fn = tcx.entry_fn(LOCAL_CRATE); + let entry_fn = tcx.entry_fn(()); debug!("collect_roots: entry_fn = {:?}", entry_fn); @@ -468,7 +468,7 @@ fn shrunk_instance_name( after = &s[positions().rev().nth(after).unwrap_or(0)..], ); - let path = tcx.output_filenames(LOCAL_CRATE).temp_path_ext("long-type.txt", None); + let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None); let written_to_path = std::fs::write(&path, s).ok().map(|_| path); (shrunk, written_to_path) diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs index edd46310f20..541c825416c 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs +++ b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs @@ -451,7 +451,9 @@ fn mono_item_visibility( let is_generic = instance.substs.non_erasable_generics().next().is_some(); // Upstream `DefId` instances get different handling than local ones. - if !def_id.is_local() { + let def_id = if let Some(def_id) = def_id.as_local() { + def_id + } else { return if export_generics && is_generic { // If it is a upstream monomorphization and we export generics, we must make // it available to downstream crates. @@ -460,7 +462,7 @@ fn mono_item_visibility( } else { Visibility::Hidden }; - } + }; if is_generic { if export_generics { @@ -470,7 +472,7 @@ fn mono_item_visibility( } else { // This instance might be useful in a downstream crate. *can_be_internalized = false; - default_visibility(tcx, def_id, true) + default_visibility(tcx, def_id.to_def_id(), true) } } else { // We are not exporting generics or the definition is not reachable @@ -481,10 +483,10 @@ fn mono_item_visibility( // If this isn't a generic function then we mark this a `Default` if // this is a reachable item, meaning that it's a symbol other crates may // access when they link to us. - if tcx.is_reachable_non_generic(def_id) { + if tcx.is_reachable_non_generic(def_id.to_def_id()) { *can_be_internalized = false; debug_assert!(!is_generic); - return default_visibility(tcx, def_id, false); + return default_visibility(tcx, def_id.to_def_id(), false); } // If this isn't reachable then we're gonna tag this with `Hidden` diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs index 333cb301590..6ed0ab8be41 100644 --- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs +++ b/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs @@ -97,7 +97,7 @@ mod merging; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync; -use rustc_hir::def_id::{CrateNum, DefIdSet, LOCAL_CRATE}; +use rustc_hir::def_id::DefIdSet; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -311,10 +311,8 @@ where fn collect_and_partition_mono_items<'tcx>( tcx: TyCtxt<'tcx>, - cnum: CrateNum, + (): (), ) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { - assert_eq!(cnum, LOCAL_CRATE); - let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items { Some(ref s) => { let mode_string = s.to_lowercase(); @@ -426,8 +424,8 @@ fn collect_and_partition_mono_items<'tcx>( (tcx.arena.alloc(mono_items), codegen_units) } -fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx DefIdSet { - let (items, cgus) = tcx.collect_and_partition_mono_items(cnum); +fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet { + let (items, cgus) = tcx.collect_and_partition_mono_items(()); let mut visited = DefIdSet::default(); let mut result = items.clone(); @@ -455,12 +453,12 @@ pub fn provide(providers: &mut Providers) { providers.codegened_and_inlined_items = codegened_and_inlined_items; providers.is_codegened_item = |tcx, def_id| { - let (all_mono_items, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); + let (all_mono_items, _) = tcx.collect_and_partition_mono_items(()); all_mono_items.contains(&def_id) }; providers.codegen_unit = |tcx, name| { - let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); + let (_, all) = tcx.collect_and_partition_mono_items(()); all.iter() .find(|cgu| cgu.name() == name) .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index ffeaaf60a30..16f5f14f563 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -141,12 +141,20 @@ impl NonConstOp for FnPtrCast { pub struct Generator(pub hir::GeneratorKind); impl NonConstOp for Generator { fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { - Status::Forbidden + if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 { + Status::Unstable(sym::const_async_blocks) + } else { + Status::Forbidden + } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind()); - ccx.tcx.sess.struct_span_err(span, &msg) + if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 { + feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg) + } else { + ccx.tcx.sess.struct_span_err(span, &msg) + } } } diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs index 48361483099..2397d627880 100644 --- a/compiler/rustc_mir/src/transform/coverage/debug.rs +++ b/compiler/rustc_mir/src/transform/coverage/debug.rs @@ -120,6 +120,7 @@ use rustc_index::vec::Idx; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{self, BasicBlock, TerminatorKind}; use rustc_middle::ty::TyCtxt; +use rustc_span::Span; use std::iter; use std::lazy::SyncOnceCell; @@ -636,6 +637,7 @@ pub(super) fn dump_coverage_spanview( mir_body: &mir::Body<'tcx>, basic_coverage_blocks: &CoverageGraph, pass_name: &str, + body_span: Span, coverage_spans: &Vec<CoverageSpan>, ) { let mir_source = mir_body.source; @@ -647,7 +649,7 @@ pub(super) fn dump_coverage_spanview( let crate_name = tcx.crate_name(def_id.krate); let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate(); let title = format!("{}.{} - Coverage Spans", crate_name, item_name); - spanview::write_document(tcx, def_id, span_viewables, &title, &mut file) + spanview::write_document(tcx, body_span, span_viewables, &title, &mut file) .expect("Unexpected IO error dumping coverage spans as HTML"); } diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs index 918d6ee4b0c..71c244fdd4a 100644 --- a/compiler/rustc_mir/src/transform/coverage/mod.rs +++ b/compiler/rustc_mir/src/transform/coverage/mod.rs @@ -95,7 +95,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); - trace!("InstrumentCoverage starting for {:?}", mir_source.def_id()); + trace!("InstrumentCoverage done for {:?}", mir_source.def_id()); } } @@ -116,25 +116,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { let def_id = mir_body.source.def_id(); let (some_fn_sig, hir_body) = fn_sig_and_body(tcx, def_id); - let mut body_span = hir_body.value.span; - - if tcx.is_closure(def_id) { - // If the MIR function is a closure, and if the closure body span - // starts from a macro, but it's content is not in that macro, try - // to find a non-macro callsite, and instrument the spans there - // instead. - loop { - let expn_data = body_span.ctxt().outer_expn_data(); - if expn_data.is_root() { - break; - } - if let ExpnKind::Macro { .. } = expn_data.kind { - body_span = expn_data.call_site; - } else { - break; - } - } - } + let body_span = get_body_span(tcx, hir_body, mir_body); let source_file = source_map.lookup_source_file(body_span.lo()); let fn_sig_span = match some_fn_sig.filter(|fn_sig| { @@ -144,6 +126,15 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { Some(fn_sig) => fn_sig.span.with_hi(body_span.lo()), None => body_span.shrink_to_lo(), }; + + debug!( + "instrumenting {}: {:?}, fn sig span: {:?}, body span: {:?}", + if tcx.is_closure(def_id) { "closure" } else { "function" }, + def_id, + fn_sig_span, + body_span + ); + let function_source_hash = hash_mir_source(tcx, hir_body); let basic_coverage_blocks = CoverageGraph::from_mir(mir_body); Self { @@ -160,19 +151,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn inject_counters(&'a mut self) { let tcx = self.tcx; - let source_map = tcx.sess.source_map(); let mir_source = self.mir_body.source; let def_id = mir_source.def_id(); let fn_sig_span = self.fn_sig_span; let body_span = self.body_span; - debug!( - "instrumenting {:?}, fn sig span: {}, body span: {}", - def_id, - source_map.span_to_diagnostic_string(fn_sig_span), - source_map.span_to_diagnostic_string(body_span) - ); - let mut graphviz_data = debug::GraphvizData::new(); let mut debug_used_expressions = debug::UsedExpressions::new(); @@ -204,6 +187,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { self.mir_body, &self.basic_coverage_blocks, self.pass_name, + body_span, &coverage_spans, ); } @@ -560,6 +544,35 @@ fn fn_sig_and_body<'tcx>( (hir::map::fn_sig(hir_node), tcx.hir().body(fn_body_id)) } +fn get_body_span<'tcx>( + tcx: TyCtxt<'tcx>, + hir_body: &rustc_hir::Body<'tcx>, + mir_body: &mut mir::Body<'tcx>, +) -> Span { + let mut body_span = hir_body.value.span; + let def_id = mir_body.source.def_id(); + + if tcx.is_closure(def_id) { + // If the MIR function is a closure, and if the closure body span + // starts from a macro, but it's content is not in that macro, try + // to find a non-macro callsite, and instrument the spans there + // instead. + loop { + let expn_data = body_span.ctxt().outer_expn_data(); + if expn_data.is_root() { + break; + } + if let ExpnKind::Macro { .. } = expn_data.kind { + body_span = expn_data.call_site; + } else { + break; + } + } + } + + body_span +} + fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { let mut hcx = tcx.create_no_span_stable_hashing_context(); hash(&mut hcx, &hir_body.value).to_smaller_hash() diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs index 2ba9d1bdc0c..760f16eae6b 100644 --- a/compiler/rustc_mir/src/transform/coverage/query.rs +++ b/compiler/rustc_mir/src/transform/coverage/query.rs @@ -120,8 +120,8 @@ impl CoverageVisitor { } } -fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo { - let mir_body = mir_body(tcx, def_id); +fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> CoverageInfo { + let mir_body = tcx.instance_mir(instance_def); let mut coverage_visitor = CoverageVisitor { // num_counters always has at least the `ZERO` counter. diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir/src/transform/coverage/spans.rs index 444b4e2ca19..f62171b3c53 100644 --- a/compiler/rustc_mir/src/transform/coverage/spans.rs +++ b/compiler/rustc_mir/src/transform/coverage/spans.rs @@ -530,17 +530,25 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { .iter() .enumerate() .filter_map(move |(index, statement)| { - filtered_statement_span(statement, self.body_span).map( - |(span, expn_span)| { - CoverageSpan::for_statement( - statement, span, expn_span, bcb, bb, index, - ) - }, - ) + filtered_statement_span(statement).map(|span| { + CoverageSpan::for_statement( + statement, + function_source_span(span, self.body_span), + span, + bcb, + bb, + index, + ) + }) }) - .chain(filtered_terminator_span(data.terminator(), self.body_span).map( - |(span, expn_span)| CoverageSpan::for_terminator(span, expn_span, bcb, bb), - )) + .chain(filtered_terminator_span(data.terminator()).map(|span| { + CoverageSpan::for_terminator( + function_source_span(span, self.body_span), + span, + bcb, + bb, + ) + })) }) .collect() } @@ -795,13 +803,9 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { } } -/// See `function_source_span()` for a description of the two returned spans. -/// If the MIR `Statement` is not contributive to computing coverage spans, -/// returns `None`. -pub(super) fn filtered_statement_span( - statement: &'a Statement<'tcx>, - body_span: Span, -) -> Option<(Span, Span)> { +/// If the MIR `Statement` has a span contributive to computing coverage spans, +/// return it; otherwise return `None`. +pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option<Span> { match statement.kind { // These statements have spans that are often outside the scope of the executed source code // for their parent `BasicBlock`. @@ -838,18 +842,14 @@ pub(super) fn filtered_statement_span( | StatementKind::LlvmInlineAsm(_) | StatementKind::Retag(_, _) | StatementKind::AscribeUserType(_, _) => { - Some(function_source_span(statement.source_info.span, body_span)) + Some(statement.source_info.span) } } } -/// See `function_source_span()` for a description of the two returned spans. -/// If the MIR `Terminator` is not contributive to computing coverage spans, -/// returns `None`. -pub(super) fn filtered_terminator_span( - terminator: &'a Terminator<'tcx>, - body_span: Span, -) -> Option<(Span, Span)> { +/// If the MIR `Terminator` has a span contributive to computing coverage spans, +/// return it; otherwise return `None`. +pub(super) fn filtered_terminator_span(terminator: &'a Terminator<'tcx>) -> Option<Span> { match terminator.kind { // These terminators have spans that don't positively contribute to computing a reasonable // span of actually executed source code. (For example, SwitchInt terminators extracted from @@ -873,7 +873,7 @@ pub(super) fn filtered_terminator_span( span = span.with_lo(constant.span.lo()); } } - Some(function_source_span(span, body_span)) + Some(span) } // Retain spans from all other terminators @@ -884,28 +884,20 @@ pub(super) fn filtered_terminator_span( | TerminatorKind::GeneratorDrop | TerminatorKind::FalseUnwind { .. } | TerminatorKind::InlineAsm { .. } => { - Some(function_source_span(terminator.source_info.span, body_span)) + Some(terminator.source_info.span) } } } -/// Returns two spans from the given span (the span associated with a -/// `Statement` or `Terminator`): -/// -/// 1. An extrapolated span (pre-expansion[^1]) corresponding to a range within -/// the function's body source. This span is guaranteed to be contained -/// within, or equal to, the `body_span`. If the extrapolated span is not -/// contained within the `body_span`, the `body_span` is returned. -/// 2. The actual `span` value from the `Statement`, before expansion. -/// -/// Only the first span is used when computing coverage code regions. The second -/// span is useful if additional expansion data is needed (such as to look up -/// the macro name for a composed span within that macro).) +/// Returns an extrapolated span (pre-expansion[^1]) corresponding to a range +/// within the function's body source. This span is guaranteed to be contained +/// within, or equal to, the `body_span`. If the extrapolated span is not +/// contained within the `body_span`, the `body_span` is returned. /// -/// [^1]Expansions result from Rust syntax including macros, syntactic -/// sugar, etc.). +/// [^1]Expansions result from Rust syntax including macros, syntactic sugar, +/// etc.). #[inline] -fn function_source_span(span: Span, body_span: Span) -> (Span, Span) { +pub(super) fn function_source_span(span: Span, body_span: Span) -> Span { let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt()); - (if body_span.contains(original_span) { original_span } else { body_span }, span) + if body_span.contains(original_span) { original_span } else { body_span } } diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir/src/transform/coverage/tests.rs index 9b84173c8a2..b04c2d542d4 100644 --- a/compiler/rustc_mir/src/transform/coverage/tests.rs +++ b/compiler/rustc_mir/src/transform/coverage/tests.rs @@ -683,12 +683,10 @@ fn test_make_bcb_counters() { let mut basic_coverage_blocks = graph::CoverageGraph::from_mir(&mir_body); let mut coverage_spans = Vec::new(); for (bcb, data) in basic_coverage_blocks.iter_enumerated() { - if let Some((span, expn_span)) = - spans::filtered_terminator_span(data.terminator(&mir_body), body_span) - { + if let Some(span) = spans::filtered_terminator_span(data.terminator(&mir_body)) { coverage_spans.push(spans::CoverageSpan::for_terminator( + spans::function_source_span(span, body_span), span, - expn_span, bcb, data.last_bb(), )); diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index f7ea9faec47..7934d4ba849 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -170,10 +170,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { } fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool { - match terminator.kind { - TerminatorKind::SwitchInt { .. } => true, - _ => false, - } + matches!(terminator.kind, TerminatorKind::SwitchInt { .. }) } struct Helper<'a, 'tcx> { diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 5c49ee69edc..2201223e13e 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -3,7 +3,7 @@ use required_consts::RequiredConstsVisitor; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::steal::Steal; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor as _; @@ -98,14 +98,13 @@ pub(crate) fn provide(providers: &mut Providers) { } fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - tcx.mir_keys(def_id.krate).contains(&def_id.expect_local()) + let def_id = def_id.expect_local(); + tcx.mir_keys(()).contains(&def_id) } /// Finds the full set of `DefId`s within the current crate that have /// MIR associated with them. -fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> FxHashSet<LocalDefId> { - assert_eq!(krate, LOCAL_CRATE); - +fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> { let mut set = FxHashSet::default(); // All body-owners have MIR associated with them. diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs index b42543c04eb..89fddc95c98 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir/src/transform/simplify_try.rs @@ -628,10 +628,7 @@ impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { // But `asm!(...)` could abort the program, // so we cannot assume that the `unreachable` terminator itself is reachable. // FIXME(Centril): use a normalization pass instead of a check. - || bb.statements.iter().any(|stmt| match stmt.kind { - StatementKind::LlvmInlineAsm(..) => true, - _ => false, - }) + || bb.statements.iter().any(|stmt| matches!(stmt.kind, StatementKind::LlvmInlineAsm(..))) }) .peekable(); diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 955e85c944a..c4e1e184ac5 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -10,7 +10,7 @@ use super::spanview::write_mir_fn_spanview; use crate::transform::MirSource; use either::Either; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{ read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, @@ -776,8 +776,8 @@ pub struct RenderAllocation<'a, 'tcx, Tag, Extra> { impl<Tag: Copy + Debug, Extra> std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> { fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; - write!(w, "size: {}, align: {})", alloc.size.bytes(), alloc.align.bytes())?; - if alloc.size == Size::ZERO { + write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?; + if alloc.size() == Size::ZERO { // We are done. return write!(w, " {{}}"); } @@ -822,9 +822,9 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>( w: &mut dyn std::fmt::Write, prefix: &str, ) -> std::fmt::Result { - let num_lines = alloc.size.bytes_usize().saturating_sub(BYTES_PER_LINE); + let num_lines = alloc.size().bytes_usize().saturating_sub(BYTES_PER_LINE); // Number of chars needed to represent all line numbers. - let pos_width = format!("{:x}", alloc.size.bytes()).len(); + let pos_width = format!("{:x}", alloc.size().bytes()).len(); if num_lines > 0 { write!(w, "{}0x{:02$x} │ ", prefix, 0, pos_width)?; @@ -845,7 +845,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>( } }; - while i < alloc.size { + while i < alloc.size() { // The line start already has a space. While we could remove that space from the line start // printing and unconditionally print a space here, that would cause the single-line case // to have a single space before it, which looks weird. @@ -929,7 +929,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>( i += Size::from_bytes(1); } // Print a new line header if the next line still has some bytes to print. - if i == line_start + Size::from_bytes(BYTES_PER_LINE) && i != alloc.size { + if i == line_start + Size::from_bytes(BYTES_PER_LINE) && i != alloc.size() { line_start = write_allocation_newline(w, line_start, &ascii, pos_width, prefix)?; ascii.clear(); } @@ -1020,6 +1020,6 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option<DefId>) -> Vec<DefId> { if let Some(i) = single { vec![i] } else { - tcx.mir_keys(LOCAL_CRATE).iter().map(|def_id| def_id.to_def_id()).collect() + tcx.mir_keys(()).iter().map(|def_id| def_id.to_def_id()).collect() } } diff --git a/compiler/rustc_mir/src/util/spanview.rs b/compiler/rustc_mir/src/util/spanview.rs index 2103f2f0934..42683dac426 100644 --- a/compiler/rustc_mir/src/util/spanview.rs +++ b/compiler/rustc_mir/src/util/spanview.rs @@ -131,7 +131,7 @@ where } } } - write_document(tcx, def_id, span_viewables, title, w)?; + write_document(tcx, fn_span(tcx, def_id), span_viewables, title, w)?; Ok(()) } @@ -139,7 +139,7 @@ where /// list `SpanViewable`s. pub fn write_document<'tcx, W>( tcx: TyCtxt<'tcx>, - def_id: DefId, + spanview_span: Span, mut span_viewables: Vec<SpanViewable>, title: &str, w: &mut W, @@ -147,16 +147,16 @@ pub fn write_document<'tcx, W>( where W: Write, { - let fn_span = fn_span(tcx, def_id); - let mut from_pos = fn_span.lo(); - let end_pos = fn_span.hi(); + let mut from_pos = spanview_span.lo(); + let end_pos = spanview_span.hi(); let source_map = tcx.sess.source_map(); let start = source_map.lookup_char_pos(from_pos); let indent_to_initial_start_col = " ".repeat(start.col.to_usize()); debug!( - "fn_span source is:\n{}{}", + "spanview_span={:?}; source is:\n{}{}", + spanview_span, indent_to_initial_start_col, - source_map.span_to_snippet(fn_span).expect("function should have printable source") + source_map.span_to_snippet(spanview_span).expect("function should have printable source") ); writeln!(w, "{}", HEADER)?; writeln!(w, "<title>{}</title>", title)?; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 933362578f9..32799cbf4c7 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -64,38 +64,30 @@ impl<'tcx> UnsafetyVisitor<'tcx> { SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { // unsafe_op_in_unsafe_fn is disallowed - if kind == BorrowOfPackedField { - // FIXME handle borrows of packed fields - } else { - struct_span_err!( - self.tcx.sess, - span, - E0133, - "{} is unsafe and requires unsafe block", - description, - ) - .span_label(span, description) - .note(note) - .emit(); - } + struct_span_err!( + self.tcx.sess, + span, + E0133, + "{} is unsafe and requires unsafe block", + description, + ) + .span_label(span, description) + .note(note) + .emit(); } SafetyContext::Safe => { - if kind == BorrowOfPackedField { - // FIXME handle borrows of packed fields - } else { - let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" }; - struct_span_err!( - self.tcx.sess, - span, - E0133, - "{} is unsafe and requires unsafe{} block", - description, - fn_sugg, - ) - .span_label(span, description) - .note(note) - .emit(); - } + let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" }; + struct_span_err!( + self.tcx.sess, + span, + E0133, + "{} is unsafe and requires unsafe{} block", + description, + fn_sugg, + ) + .span_label(span, description) + .note(note) + .emit(); } } } @@ -153,6 +145,9 @@ impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> { self.requires_unsafe(expr.span, CallToUnsafeFunction); } } + ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => { + self.requires_unsafe(expr.span, UseOfInlineAssembly); + } _ => {} } @@ -194,15 +189,12 @@ impl BodyUnsafety { #[derive(Clone, Copy, PartialEq)] enum UnsafeOpKind { CallToUnsafeFunction, - #[allow(dead_code)] // FIXME UseOfInlineAssembly, #[allow(dead_code)] // FIXME InitializingTypeWith, #[allow(dead_code)] // FIXME CastOfPointerToInt, #[allow(dead_code)] // FIXME - BorrowOfPackedField, - #[allow(dead_code)] // FIXME UseOfMutableStatic, #[allow(dead_code)] // FIXME UseOfExternStatic, @@ -242,11 +234,6 @@ impl UnsafeOpKind { CastOfPointerToInt => { ("cast of pointer to int", "casting pointers to integers in constants") } - BorrowOfPackedField => ( - "borrow of packed field", - "fields of packed structs might be misaligned: dereferencing a misaligned pointer \ - or even just creating a misaligned reference is undefined behavior", - ), UseOfMutableStatic => ( "use of mutable static", "mutable statics can be mutated by multiple threads: aliasing violations or data \ diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index b2b578f1ed4..c64fab0507c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1236,7 +1236,7 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - fn parse_record_struct_body( + pub(super) fn parse_record_struct_body( &mut self, adt_ty: &str, ) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> { @@ -1470,19 +1470,25 @@ impl<'a> Parser<'a> { fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { - let err = if self.check_fn_front_matter(false) { - let _ = self.parse_fn(&mut Vec::new(), |_| true, lo); - let mut err = self.struct_span_err( - lo.to(self.prev_token.span), - &format!("functions are not allowed in {} definitions", adt_ty), - ); - err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks"); - err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); - err + if ident.name == kw::Underscore { + self.sess.gated_spans.gate(sym::unnamed_fields, lo); } else { - self.expected_ident_found() - }; - return Err(err); + let err = if self.check_fn_front_matter(false) { + let _ = self.parse_fn(&mut Vec::new(), |_| true, lo); + let mut err = self.struct_span_err( + lo.to(self.prev_token.span), + &format!("functions are not allowed in {} definitions", adt_ty), + ); + err.help( + "unlike in C++, Java, and C#, functions are declared in `impl` blocks", + ); + err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); + err + } else { + self.expected_ident_found() + }; + return Err(err); + } } self.bump(); Ok(ident) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 35cfaae13a4..4c2bc6ebf31 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1065,24 +1065,11 @@ impl<'a> Parser<'a> { } else if !delimited_only { if self.eat(&token::Eq) { let eq_span = self.prev_token.span; - let mut is_interpolated_expr = false; - if let token::Interpolated(nt) = &self.token.kind { - if let token::NtExpr(..) = **nt { - is_interpolated_expr = true; - } - } // Collect tokens because they are used during lowering to HIR. let expr = self.parse_expr_force_collect()?; let span = expr.span; - match &expr.kind { - // Not gated to support things like `doc = $expr` that work on stable. - _ if is_interpolated_expr => {} - ExprKind::Lit(lit) if lit.kind.is_unsuffixed() => {} - _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span), - } - let token_kind = token::Interpolated(Lrc::new(token::NtExpr(expr))); MacArgs::Eq(eq_span, Token::new(token_kind, span)) } else { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index d537741c749..89cf2d7876e 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -226,6 +226,19 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(kw::Impl) { self.parse_impl_ty(&mut impl_dyn_multi)? + } else if self.token.is_keyword(kw::Union) + && self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) + { + self.bump(); + let (fields, recovered) = self.parse_record_struct_body("union")?; + let span = lo.to(self.prev_token.span); + self.sess.gated_spans.gate(sym::unnamed_fields, span); + TyKind::AnonymousUnion(fields, recovered) + } else if self.eat_keyword(kw::Struct) { + let (fields, recovered) = self.parse_record_struct_body("struct")?; + let span = lo.to(self.prev_token.span); + self.sess.gated_spans.gate(sym::unnamed_fields, span); + TyKind::AnonymousStruct(fields, recovered) } else if self.is_explicit_dyn_type() { self.parse_dyn_ty(&mut impl_dyn_multi)? } else if self.eat_lt() { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d32180525bf..bef56bbc287 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{Node, PatKind, TyKind}; @@ -44,6 +44,7 @@ struct MarkSymbolVisitor<'tcx> { repr_has_repr_c: bool, in_pat: bool, inherited_pub_visibility: bool, + pub_visibility: bool, ignore_variant_stack: Vec<DefId>, // maps from tuple struct constructors to tuple struct items struct_constructors: FxHashMap<hir::HirId, hir::HirId>, @@ -188,27 +189,33 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn visit_node(&mut self, node: Node<'tcx>) { let had_repr_c = self.repr_has_repr_c; - self.repr_has_repr_c = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; + let had_pub_visibility = self.pub_visibility; + self.repr_has_repr_c = false; self.inherited_pub_visibility = false; + self.pub_visibility = false; match node { - Node::Item(item) => match item.kind { - hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(item.def_id); - self.repr_has_repr_c = def.repr.c(); + Node::Item(item) => { + self.pub_visibility = item.vis.node.is_pub(); - intravisit::walk_item(self, &item); - } - hir::ItemKind::Enum(..) => { - self.inherited_pub_visibility = item.vis.node.is_pub(); + match item.kind { + hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { + let def = self.tcx.adt_def(item.def_id); + self.repr_has_repr_c = def.repr.c(); - intravisit::walk_item(self, &item); - } - hir::ItemKind::ForeignMod { .. } => {} - _ => { - intravisit::walk_item(self, &item); + intravisit::walk_item(self, &item); + } + hir::ItemKind::Enum(..) => { + self.inherited_pub_visibility = self.pub_visibility; + + intravisit::walk_item(self, &item); + } + hir::ItemKind::ForeignMod { .. } => {} + _ => { + intravisit::walk_item(self, &item); + } } - }, + } Node::TraitItem(trait_item) => { intravisit::walk_trait_item(self, trait_item); } @@ -220,8 +227,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } _ => {} } - self.repr_has_repr_c = had_repr_c; + self.pub_visibility = had_pub_visibility; self.inherited_pub_visibility = had_inherited_pub_visibility; + self.repr_has_repr_c = had_repr_c; } fn mark_as_used_if_union(&mut self, adt: &ty::AdtDef, fields: &[hir::ExprField<'_>]) { @@ -259,10 +267,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { ) { let has_repr_c = self.repr_has_repr_c; let inherited_pub_visibility = self.inherited_pub_visibility; - let live_fields = def - .fields() - .iter() - .filter(|f| has_repr_c || inherited_pub_visibility || f.vis.node.is_pub()); + let pub_visibility = self.pub_visibility; + let live_fields = def.fields().iter().filter(|f| { + has_repr_c || (pub_visibility && (inherited_pub_visibility || f.vis.node.is_pub())) + }); self.live_symbols.extend(live_fields.map(|f| f.hir_id)); intravisit::walk_struct_def(self, def); @@ -472,7 +480,7 @@ fn create_and_seed_worklist<'tcx>( ) .chain( // Seed entry point - tcx.entry_fn(LOCAL_CRATE).and_then(|(def_id, _)| { + tcx.entry_fn(()).and_then(|(def_id, _)| { def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) }), ) @@ -500,6 +508,7 @@ fn find_live<'tcx>( repr_has_repr_c: false, in_pat: false, inherited_pub_visibility: false, + pub_visibility: false, ignore_variant_stack: vec![], struct_constructors, }; @@ -708,7 +717,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } pub fn check_crate(tcx: TyCtxt<'_>) { - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); + let access_levels = &tcx.privacy_access_levels(()); let krate = tcx.hir().krate(); let live_symbols = find_live(tcx, access_levels, krate); let mut visitor = DeadVisitor { tcx, live_symbols }; diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 8dd3700e5b6..f345d45d178 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -16,7 +16,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_span::symbol::{sym, Symbol}; struct DiagnosticItemCollector<'tcx> { @@ -99,7 +99,9 @@ fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option<Symbol> { } /// Traverse and collect the diagnostic items in the current -fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> { +fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap<Symbol, DefId> { + assert_eq!(cnum, LOCAL_CRATE); + // Initialize the collector. let mut collector = DiagnosticItemCollector::new(tcx); @@ -114,7 +116,7 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> { } /// Traverse and collect all the diagnostic items in all crates. -fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> { +fn all_diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashMap<Symbol, DefId> { // Initialize the collector. let mut collector = FxHashMap::default(); @@ -129,12 +131,6 @@ fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> { } pub fn provide(providers: &mut Providers) { - providers.diagnostic_items = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - collect(tcx) - }; - providers.all_diagnostic_items = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - collect_all(tcx) - }; + providers.diagnostic_items = diagnostic_items; + providers.all_diagnostic_items = all_diagnostic_items; } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 65cfe986ad4..ca6a7561f3e 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,6 +1,6 @@ use rustc_ast::entry::EntryPointType; use rustc_errors::struct_span_err; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{ForeignItem, HirId, ImplItem, Item, ItemKind, TraitItem, CRATE_HIR_ID}; use rustc_middle::hir::map::Map; @@ -48,9 +48,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { } } -fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { - assert_eq!(cnum, LOCAL_CRATE); - +fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); if !any_exe { // No need to find a main function. @@ -227,10 +225,6 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { err.emit(); } -pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> { - tcx.entry_fn(LOCAL_CRATE) -} - pub fn provide(providers: &mut Providers) { *providers = Providers { entry_fn, ..*providers }; } diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 4532a0a350c..012d97ef106 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -347,7 +347,7 @@ impl ExprVisitor<'tcx> { } fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { - for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { + for (idx, (op, _)) in asm.operands.iter().enumerate() { match *op { hir::InlineAsmOperand::In { reg, ref expr } => { self.check_asm_operand_type(idx, reg, expr, asm.template, None); @@ -372,19 +372,7 @@ impl ExprVisitor<'tcx> { ); } } - hir::InlineAsmOperand::Const { ref anon_const } => { - let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); - match value.ty.kind() { - ty::Int(_) | ty::Uint(_) | ty::Float(_) => {} - _ => { - let msg = - "asm `const` arguments must be integer or floating-point values"; - self.tcx.sess.span_err(*op_sp, msg); - } - } - } - hir::InlineAsmOperand::Sym { .. } => {} + hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {} } } } @@ -405,33 +393,6 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> { ExprVisitor { tcx: self.tcx, param_env, typeck_results }.visit_body(body); self.visit_body(body); } - - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - if let hir::ItemKind::GlobalAsm(asm) = item.kind { - for (op, op_sp) in asm.operands { - match *op { - hir::InlineAsmOperand::Const { ref anon_const } => { - let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); - match value.ty.kind() { - ty::Int(_) | ty::Uint(_) | ty::Float(_) => {} - _ => { - let msg = "asm `const` arguments must be integer or floating-point values"; - self.tcx.sess.span_err(*op_sp, msg); - } - } - } - hir::InlineAsmOperand::In { .. } - | hir::InlineAsmOperand::Out { .. } - | hir::InlineAsmOperand::InOut { .. } - | hir::InlineAsmOperand::SplitInOut { .. } - | hir::InlineAsmOperand::Sym { .. } => unreachable!(), - } - } - } - - intravisit::walk_item(self, item); - } } impl Visitor<'tcx> for ExprVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 7e6bb9779f0..118fcca4508 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -13,12 +13,13 @@ use crate::weak_lang_items; use rustc_middle::middle::cstore::ExternCrate; use rustc_middle::ty::TyCtxt; -use rustc_errors::struct_span_err; +use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::lang_items::{extract, ITEM_REFS}; use rustc_hir::{HirId, LangItem, LanguageItems, Target}; +use rustc_span::Span; use rustc_middle::ty::query::Providers; @@ -61,8 +62,7 @@ impl LanguageItemCollector<'tcx> { match ITEM_REFS.get(&value).cloned() { // Known lang item with attribute on correct target. Some((item_index, expected_target)) if actual_target == expected_target => { - let def_id = self.tcx.hir().local_def_id(hir_id); - self.collect_item(item_index, def_id.to_def_id()); + self.collect_item_extended(item_index, hir_id, span); } // Known lang item with attribute on incorrect target. Some((_, expected_target)) => { @@ -180,10 +180,131 @@ impl LanguageItemCollector<'tcx> { self.items.groups[group as usize].push(item_def_id); } } + + // Like collect_item() above, but also checks whether the lang item is declared + // with the right number of generic arguments if it is a trait. + fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) { + let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id(); + let lang_item = LangItem::from_u32(item_index as u32).unwrap(); + let name = lang_item.name(); + + self.collect_item(item_index, item_def_id); + + // Now check whether the lang_item has the expected number of generic + // arguments if it is a trait. Generally speaking, binary and indexing + // operations have one (for the RHS/index), unary operations have none, + // and the rest also have none except for the closure traits (one for + // the argument list), generators (one for the resume argument), + // ordering/equality relations (one for the RHS), and various conversion + // traits. + + let expected_num = match lang_item { + // Binary operations + LangItem::Add + | LangItem::Sub + | LangItem::Mul + | LangItem::Div + | LangItem::Rem + | LangItem::BitXor + | LangItem::BitAnd + | LangItem::BitOr + | LangItem::Shl + | LangItem::Shr + | LangItem::AddAssign + | LangItem::SubAssign + | LangItem::MulAssign + | LangItem::DivAssign + | LangItem::RemAssign + | LangItem::BitXorAssign + | LangItem::BitAndAssign + | LangItem::BitOrAssign + | LangItem::ShlAssign + | LangItem::ShrAssign + | LangItem::Index + | LangItem::IndexMut + + // Miscellaneous + | LangItem::Unsize + | LangItem::CoerceUnsized + | LangItem::DispatchFromDyn + | LangItem::Fn + | LangItem::FnMut + | LangItem::FnOnce + | LangItem::Generator + | LangItem::PartialEq + | LangItem::PartialOrd + => Some(1), + + // Unary operations + LangItem::Neg + | LangItem::Not + + // Miscellaneous + | LangItem::Deref + | LangItem::DerefMut + | LangItem::Sized + | LangItem::StructuralPeq + | LangItem::StructuralTeq + | LangItem::Copy + | LangItem::Clone + | LangItem::Sync + | LangItem::DiscriminantKind + | LangItem::PointeeTrait + | LangItem::Freeze + | LangItem::Drop + | LangItem::Receiver + | LangItem::Future + | LangItem::Unpin + | LangItem::Termination + | LangItem::Try + | LangItem::Send + | LangItem::UnwindSafe + | LangItem::RefUnwindSafe + => Some(0), + + // Not a trait + _ => None, + }; + + if let Some(expected_num) = expected_num { + let (actual_num, generics_span) = match self.tcx.hir().get(hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Trait(_, _, generics, ..), + .. + }) => (generics.params.len(), generics.span), + _ => bug!("op/index/deref lang item target is not a trait: {:?}", lang_item), + }; + + if expected_num != actual_num { + // We are issuing E0718 "incorrect target" here, because while the + // item kind of the target is correct, the target is still wrong + // because of the wrong number of generic arguments. + struct_span_err!( + self.tcx.sess, + span, + E0718, + "`{}` language item must be applied to a trait with {} generic argument{}", + name, + expected_num, + pluralize!(expected_num) + ) + .span_label( + generics_span, + format!( + "this trait has {} generic argument{}, not {}", + actual_num, + pluralize!(actual_num), + expected_num + ), + ) + .emit(); + } + } + } } /// Traverses and collects all the lang items in all crates. -fn collect(tcx: TyCtxt<'_>) -> LanguageItems { +fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { // Initialize the collector. let mut collector = LanguageItemCollector::new(tcx); @@ -207,8 +328,5 @@ fn collect(tcx: TyCtxt<'_>) -> LanguageItems { } pub fn provide(providers: &mut Providers) { - providers.get_lang_items = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - collect(tcx) - }; + providers.get_lang_items = get_lang_items; } diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 3dfe317a4bd..363a6417f99 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -6,7 +6,6 @@ use rustc_ast::{Attribute, MetaItem, MetaItemKind}; use rustc_errors::struct_span_err; -use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_middle::hir::map::Map; use rustc_middle::middle::lib_features::LibFeatures; @@ -127,7 +126,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> { } } -fn collect(tcx: TyCtxt<'_>) -> LibFeatures { +fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); let krate = tcx.hir().krate(); for attr in krate.non_exported_macro_attrs { @@ -138,8 +137,5 @@ fn collect(tcx: TyCtxt<'_>) -> LibFeatures { } pub fn provide(providers: &mut Providers) { - providers.get_lib_features = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - collect(tcx) - }; + providers.get_lib_features = get_lib_features; } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 20aaaea5b98..0b3227abb5f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -8,8 +8,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::Node; @@ -250,7 +249,7 @@ impl<'tcx> ReachableContext<'tcx> { // Reachable constants will be inlined into other crates // unconditionally, so we need to make sure that their // contents are also reachable. - hir::ItemKind::Const(_, init) => { + hir::ItemKind::Const(_, init) | hir::ItemKind::Static(_, _, init) => { self.visit_nested_body(init); } @@ -261,7 +260,6 @@ impl<'tcx> ReachableContext<'tcx> { | hir::ItemKind::Use(..) | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::TyAlias(..) - | hir::ItemKind::Static(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } @@ -386,10 +384,8 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx } } -fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> { - debug_assert!(crate_num == LOCAL_CRATE); - - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); +fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> { + let access_levels = &tcx.privacy_access_levels(()); let any_library = tcx.sess.crate_types().iter().any(|ty| { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 6b1813fba76..f41e0e03706 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -629,7 +629,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { // stable (assuming they have not inherited instability from their parent). } -fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { +fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { let is_staged_api = tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api; let mut staged_api = FxHashMap::default(); @@ -704,11 +704,7 @@ fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_unstable_api_usage, ..*providers }; - providers.stability_index = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - new_index(tcx) - }; + *providers = Providers { check_mod_unstable_api_usage, stability_index, ..*providers }; } struct Checker<'tcx> { @@ -880,7 +876,7 @@ impl Visitor<'tcx> for CheckTraitImplStable<'tcx> { /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); + let access_levels = &tcx.privacy_access_levels(()); if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir().krate(); diff --git a/compiler/rustc_plugin_impl/src/build.rs b/compiler/rustc_plugin_impl/src/build.rs index a49afa35e46..b95c4a72019 100644 --- a/compiler/rustc_plugin_impl/src/build.rs +++ b/compiler/rustc_plugin_impl/src/build.rs @@ -1,7 +1,7 @@ //! Used by `rustc` when compiling a plugin crate. use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::LocalDefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; @@ -31,33 +31,25 @@ impl<'v, 'tcx> ItemLikeVisitor<'v> for RegistrarFinder<'tcx> { } /// Finds the function marked with `#[plugin_registrar]`, if any. -pub fn find_plugin_registrar(tcx: TyCtxt<'_>) -> Option<DefId> { - tcx.plugin_registrar_fn(LOCAL_CRATE) -} - -fn plugin_registrar_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> { - assert_eq!(cnum, LOCAL_CRATE); - +fn plugin_registrar_fn(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> { let mut finder = RegistrarFinder { tcx, registrars: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut finder); - match finder.registrars.len() { - 0 => None, - 1 => { - let (def_id, _) = finder.registrars.pop().unwrap(); - Some(def_id.to_def_id()) - } - _ => { - let diagnostic = tcx.sess.diagnostic(); - let mut e = diagnostic.struct_err("multiple plugin registration functions found"); - for &(_, span) in &finder.registrars { - e.span_note(span, "one is here"); - } - e.emit(); - diagnostic.abort_if_errors(); - unreachable!(); + let (def_id, span) = finder.registrars.pop()?; + + if !finder.registrars.is_empty() { + let diagnostic = tcx.sess.diagnostic(); + let mut e = diagnostic.struct_err("multiple plugin registration functions found"); + e.span_note(span, "one is here"); + for &(_, span) in &finder.registrars { + e.span_note(span, "one is here"); } + e.emit(); + diagnostic.abort_if_errors(); + unreachable!(); } + + Some(def_id) } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d37a5be2fe5..1342762bb07 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor}; use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; use rustc_middle::bug; @@ -2092,9 +2092,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { intravisit::walk_mod(&mut visitor, module, hir_id); } -fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels { - assert_eq!(krate, LOCAL_CRATE); - +fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels { // Build up a set of all exported items in the AST. This is a set of all // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { @@ -2117,10 +2115,8 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels { tcx.arena.alloc(visitor.access_levels) } -fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) { - assert_eq!(krate, LOCAL_CRATE); - - let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); +fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { + let access_levels = tcx.privacy_access_levels(()); let krate = tcx.hir().krate(); diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 1fdb37398f9..27a0dc47682 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -21,6 +21,16 @@ pub trait Key { fn default_span(&self, tcx: TyCtxt<'_>) -> Span; } +impl Key for () { + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + + fn default_span(&self, _: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + impl<'tcx> Key for ty::InstanceDef<'tcx> { fn query_crate(&self) -> CrateNum { LOCAL_CRATE diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index bcd125ae01d..6c308ad89db 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> { let sess = &self.tcx.sess; // Save-analysis is emitted per whole session, not per each crate type let crate_type = sess.crate_types()[0]; - let outputs = &*self.tcx.output_filenames(LOCAL_CRATE); + let outputs = &*self.tcx.output_filenames(()); if outputs.outputs.contains_key(&OutputType::Metadata) { filename_for_metadata(sess, crate_name, outputs) @@ -1000,7 +1000,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( // Privacy checking requires and is done after type checking; use a // fallback in case the access levels couldn't have been correctly computed. let access_levels = match tcx.sess.compile_status() { - Ok(..) => tcx.privacy_access_levels(LOCAL_CRATE), + Ok(..) => tcx.privacy_access_levels(()), Err(..) => tcx.arena.alloc(AccessLevels::default()), }; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0b3dece09ae..14ee083ecee 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -130,10 +130,12 @@ symbols! { BTreeSet, BinaryHeap, Borrow, + Break, C, CString, Center, Clone, + Continue, Copy, Count, Debug, @@ -326,6 +328,7 @@ symbols! { box_patterns, box_syntax, braced_empty_structs, + branch, breakpoint, bridge, bswap, @@ -374,6 +377,7 @@ symbols! { conservative_impl_trait, console, const_allocate, + const_async_blocks, const_compare_raw_pointers, const_constructor, const_eval_limit, @@ -410,6 +414,7 @@ symbols! { constructor, contents, context, + control_flow_enum, convert, copy, copy_closures, @@ -510,7 +515,6 @@ symbols! { env, eq, ermsb_target_feature, - err, exact_div, except, exchange_malloc, @@ -580,10 +584,10 @@ symbols! { frem_fast, from, from_desugaring, - from_error, from_generator, from_method, - from_ok, + from_output, + from_residual, from_size_align_unchecked, from_trait, from_usize, @@ -652,7 +656,6 @@ symbols! { instruction_set, intel, into_iter, - into_result, into_trait, intra_doc_pointers, intrinsics, @@ -964,6 +967,7 @@ symbols! { repr_packed, repr_simd, repr_transparent, + residual, result, result_type, rhs, @@ -1015,6 +1019,7 @@ symbols! { rustc_expected_cgu_reuse, rustc_if_this_changed, rustc_inherit_overflow_checks, + rustc_insignificant_dtor, rustc_layout, rustc_layout_scalar_valid_range_end, rustc_layout_scalar_valid_range_start, @@ -1230,7 +1235,7 @@ symbols! { try_blocks, try_from_trait, try_into_trait, - try_trait, + try_trait_v2, tt, tuple, tuple_from_req, @@ -1268,6 +1273,7 @@ symbols! { unix, unlikely, unmarked_api, + unnamed_fields, unpin, unreachable, unreachable_code, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index c050bbc9b9d..7fb24ad1ed8 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -165,11 +165,11 @@ fn compute_symbol_name( // FIXME(eddyb) Precompute a custom symbol name based on attributes. let is_foreign = if let Some(def_id) = def_id.as_local() { - if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id.to_def_id()) { + if tcx.plugin_registrar_fn(()) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); return tcx.sess.generate_plugin_registrar_symbol(disambiguator); } - if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id.to_def_id()) { + if tcx.proc_macro_decls_static(()) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); return tcx.sess.generate_proc_macro_decls_symbol(disambiguator); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 37a834043f6..a70b374fc6d 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -485,9 +485,39 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { mut self, predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, ) -> Result<Self::DynExistential, Self::Error> { - for predicate in predicates { - self = self.in_binder(&predicate, |mut cx, predicate| { - match predicate { + // Okay, so this is a bit tricky. Imagine we have a trait object like + // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the + // output looks really close to the syntax, where the `Bar = &'a ()` bit + // is under the same binders (`['a]`) as the `Foo<'a>` bit. However, we + // actually desugar these into two separate `ExistentialPredicate`s. We + // can't enter/exit the "binder scope" twice though, because then we + // would mangle the binders twice. (Also, side note, we merging these + // two is kind of difficult, because of potential HRTBs in the Projection + // predicate.) + // + // Also worth mentioning: imagine that we instead had + // `dyn for<'a> Foo<'a, Bar = &'a ()> + Send`. In this case, `Send` is + // under the same binders as `Foo`. Currently, this doesn't matter, + // because only *auto traits* are allowed other than the principal trait + // and all auto traits don't have any generics. Two things could + // make this not an "okay" mangling: + // 1) Instead of mangling only *used* + // bound vars, we want to mangle *all* bound vars (`for<'b> Send` is a + // valid trait predicate); + // 2) We allow multiple "principal" traits in the future, or at least + // allow in any form another trait predicate that can take generics. + // + // Here we assume that predicates have the following structure: + // [<Trait> [{<Projection>}]] [{<Auto>}] + // Since any predicates after the first one shouldn't change the binders, + // just put them all in the binders of the first. + self = self.in_binder(&predicates[0], |mut cx, _| { + for predicate in predicates.iter() { + // It would be nice to be able to validate bound vars here, but + // projections can actually include bound vars from super traits + // because of HRTBs (only in the `Self` type). Also, auto traits + // could have different bound vars *anyways*. + match predicate.as_ref().skip_binder() { ty::ExistentialPredicate::Trait(trait_ref) => { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0)); @@ -504,9 +534,10 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { cx = cx.print_def_path(*def_id, &[])?; } } - Ok(cx) - })?; - } + } + Ok(cx) + })?; + self.push("E"); Ok(self) } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index f12debb5a34..c17c2961434 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -6,7 +6,6 @@ use rustc_span::Symbol; use std::fmt; use std::str::FromStr; -#[macro_use] macro_rules! def_reg_class { ($arch:ident $arch_regclass:ident { $( @@ -51,7 +50,6 @@ macro_rules! def_reg_class { } } -#[macro_use] macro_rules! def_regs { ($arch:ident $arch_reg:ident $arch_regclass:ident { $( @@ -129,7 +127,6 @@ macro_rules! def_regs { } } -#[macro_use] macro_rules! types { ( $(_ : $($ty:expr),+;)? @@ -184,6 +181,7 @@ pub enum InlineAsmArch { Mips, Mips64, PowerPC, + PowerPC64, SpirV, Wasm32, } @@ -201,6 +199,7 @@ impl FromStr for InlineAsmArch { "riscv64" => Ok(Self::RiscV64), "nvptx64" => Ok(Self::Nvptx64), "powerpc" => Ok(Self::PowerPC), + "powerpc64" => Ok(Self::PowerPC64), "hexagon" => Ok(Self::Hexagon), "mips" => Ok(Self::Mips), "mips64" => Ok(Self::Mips64), @@ -290,7 +289,7 @@ impl InlineAsmReg { InlineAsmArch::Nvptx64 => { Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?) } - InlineAsmArch::PowerPC => { + InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?) } InlineAsmArch::Hexagon => { @@ -485,7 +484,9 @@ impl InlineAsmRegClass { Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?) } InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?), - InlineAsmArch::PowerPC => Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { + Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?) + } InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?) @@ -653,7 +654,7 @@ pub fn allocatable_registers( nvptx::fill_reg_map(arch, has_feature, target, &mut map); map } - InlineAsmArch::PowerPC => { + InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { let mut map = powerpc::regclass_map(); powerpc::fill_reg_map(arch, has_feature, target, &mut map); map diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index b254e5f3aaa..42fc25c4ff5 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -33,10 +33,16 @@ impl PowerPCInlineAsmRegClass { pub fn supported_types( self, - _arch: InlineAsmArch, + arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<&'static str>)] { match self { - Self::reg | Self::reg_nonzero => types! { _: I8, I16, I32; }, + Self::reg | Self::reg_nonzero => { + if arch == InlineAsmArch::PowerPC { + types! { _: I8, I16, I32; } + } else { + types! { _: I8, I16, I32, I64; } + } + } Self::freg => types! { _: F32, F64; }, } } diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs index 35a52896f6f..5808391ee06 100644 --- a/compiler/rustc_target/src/spec/windows_gnu_base.rs +++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs @@ -66,6 +66,7 @@ pub fn opts() -> TargetOptions { // FIXME(#13846) this should be enabled for windows function_sections: false, linker: Some("gcc".to_string()), + linker_is_gnu: true, dynamic_linking: true, executables: true, dll_prefix: String::new(), diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index fb4a8ce687c..7e67bc118ec 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -46,6 +46,7 @@ pub struct OpaqueTypeDecl<'tcx> { /// type Foo = impl Baz; /// fn bar() -> Foo { /// // ^^^ This is the span we are looking for! + /// } /// ``` /// /// In cases where the fn returns `(impl Trait, impl Trait)` or diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index da5a1af7f77..db396356d67 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -14,7 +14,7 @@ use crate::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; use rustc_middle::mir::abstract_const::NotConstEvaluatable; @@ -1427,7 +1427,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) }; let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); - let all_traits = self.tcx.all_traits(LOCAL_CRATE); + let all_traits = self.tcx.all_traits(()); let traits_with_same_path: std::collections::BTreeSet<_> = all_traits .iter() .filter(|trait_def_id| **trait_def_id != trait_ref.def_id()) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6a4d41ffc1a..8bbd2da5375 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -686,17 +686,36 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; } + // Blacklist traits for which it would be nonsensical to suggest borrowing. + // For instance, immutable references are always Copy, so suggesting to + // borrow would always succeed, but it's probably not what the user wanted. + let blacklist: Vec<_> = + [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized, LangItem::Send] + .iter() + .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok()) + .collect(); + let span = obligation.cause.span; let param_env = obligation.param_env; let trait_ref = trait_ref.skip_binder(); - if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code { - // Try to apply the original trait binding obligation by borrowing. - let self_ty = trait_ref.self_ty(); - let found = self_ty.to_string(); - let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty); - let substs = self.tcx.mk_substs_trait(new_self_ty, &[]); - let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs); + let found_ty = trait_ref.self_ty(); + let found_ty_str = found_ty.to_string(); + let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty); + let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]); + let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty); + let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]); + + // Try to apply the original trait binding obligation by borrowing. + let mut try_borrowing = |new_trait_ref: ty::TraitRef<'tcx>, + expected_trait_ref: ty::TraitRef<'tcx>, + mtbl: bool, + blacklist: &[DefId]| + -> bool { + if blacklist.contains(&expected_trait_ref.def_id) { + return false; + } + let new_obligation = Obligation::new( ObligationCause::dummy(), param_env, @@ -713,8 +732,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", - found, - obligation.parent_trait_ref.skip_binder().print_only_trait_path(), + found_ty_str, + expected_trait_ref.print_only_trait_path(), ); if has_custom_message { err.note(&msg); @@ -730,7 +749,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, &format!( "expected an implementor of trait `{}`", - obligation.parent_trait_ref.skip_binder().print_only_trait_path(), + expected_trait_ref.print_only_trait_path(), ), ); @@ -745,16 +764,52 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_suggestion( span, - "consider borrowing here", - format!("&{}", snippet), + &format!( + "consider{} borrowing here", + if mtbl { " mutably" } else { "" } + ), + format!("&{}{}", if mtbl { "mut " } else { "" }, snippet), Applicability::MaybeIncorrect, ); } return true; } } + return false; + }; + + if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code { + let expected_trait_ref = obligation.parent_trait_ref.skip_binder(); + let new_imm_trait_ref = + ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs); + let new_mut_trait_ref = + ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs); + if try_borrowing(new_imm_trait_ref, expected_trait_ref, false, &[]) { + return true; + } else { + return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]); + } + } else if let ObligationCauseCode::BindingObligation(_, _) + | ObligationCauseCode::ItemObligation(_) = &obligation.cause.code + { + if try_borrowing( + ty::TraitRef::new(trait_ref.def_id, imm_substs), + trait_ref, + false, + &blacklist[..], + ) { + return true; + } else { + return try_borrowing( + ty::TraitRef::new(trait_ref.def_id, mut_substs), + trait_ref, + true, + &blacklist[..], + ); + } + } else { + false } - false } /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 64f82817d39..bc8f10e15db 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::subst::Subst; use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::Limit; -use rustc_span::DUMMY_SP; +use rustc_span::{sym, DUMMY_SP}; type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>; @@ -21,6 +21,19 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> res } +fn has_significant_drop_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, +) -> bool { + let significant_drop_fields = + move |adt_def: &ty::AdtDef| tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter()); + let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields) + .next() + .is_some(); + debug!("has_significant_drop_raw({:?}) = {:?}", query, res); + res +} + struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -155,12 +168,20 @@ where } } -fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> { +// This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`. +// Depending on the implentation of `adt_has_dtor`, it is used to check if the +// ADT has a destructor or if the ADT only has a significant destructor. For +// understanding significant destructor look at `adt_significant_drop_tys`. +fn adt_drop_tys_helper( + tcx: TyCtxt<'_>, + def_id: DefId, + adt_has_dtor: impl Fn(&ty::AdtDef) -> bool, +) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> { let adt_components = move |adt_def: &ty::AdtDef| { if adt_def.is_manually_drop() { debug!("adt_drop_tys: `{:?}` is manually drop", adt_def); return Ok(Vec::new().into_iter()); - } else if adt_def.destructor(tcx).is_some() { + } else if adt_has_dtor(adt_def) { debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def); return Err(AlwaysRequiresDrop); } else if adt_def.is_union() { @@ -179,6 +200,30 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw res.map(|components| tcx.intern_type_list(&components)) } +fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> { + let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).is_some(); + adt_drop_tys_helper(tcx, def_id, adt_has_dtor) +} + +fn adt_significant_drop_tys( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> { + let adt_has_dtor = |adt_def: &ty::AdtDef| { + adt_def + .destructor(tcx) + .map(|dtor| !tcx.has_attr(dtor.did, sym::rustc_insignificant_dtor)) + .unwrap_or(false) + }; + adt_drop_tys_helper(tcx, def_id, adt_has_dtor) +} + pub(crate) fn provide(providers: &mut ty::query::Providers) { - *providers = ty::query::Providers { needs_drop_raw, adt_drop_tys, ..*providers }; + *providers = ty::query::Providers { + needs_drop_raw, + has_significant_drop_raw, + adt_drop_tys, + adt_significant_drop_tys, + ..*providers + }; } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 5285c1c8598..ef195621044 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1394,11 +1394,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) }); + // N.b. principal, projections, auto traits + // FIXME: This is actually wrong with multiple principals in regards to symbol mangling let mut v = regular_trait_predicates - .chain(auto_trait_predicates) .chain( existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), ) + .chain(auto_trait_predicates) .collect::<SmallVec<[_; 8]>>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); v.dedup(); diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index e40aa914858..5f26e701c0a 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -89,19 +89,31 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> { if let Some((unresolved_type, unresolved_type_span)) = self.fcx.unresolved_type_vars(&ty) { - let note = format!( - "the type is part of the {} because of this {}", - self.kind, yield_data.source - ); - // If unresolved type isn't a ty_var then unresolved_type_span is None let span = self .prev_unresolved_span .unwrap_or_else(|| unresolved_type_span.unwrap_or(source_span)); - self.fcx - .need_type_info_err_in_generator(self.kind, span, unresolved_type) - .span_note(yield_data.span, &*note) - .emit(); + + // If we encounter an int/float variable, then inference fallback didn't + // finish due to some other error. Don't emit spurious additional errors. + if let ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_)) = + unresolved_type.kind() + { + self.fcx + .tcx + .sess + .delay_span_bug(span, &format!("Encountered var {:?}", unresolved_type)); + } else { + let note = format!( + "the type is part of the {} because of this {}", + self.kind, yield_data.source + ); + + self.fcx + .need_type_info_err_in_generator(self.kind, span, unresolved_type) + .span_note(yield_data.span, &*note) + .emit(); + } } else { // Insert the type into the ordered set. let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree)); diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 0b1129a6312..427102afee1 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -303,8 +303,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { opt_input_types: Option<&[Ty<'tcx>]>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { debug!( - "lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?})", - self_ty, m_name, trait_def_id + "lookup_in_trait_adjusted(self_ty={:?}, m_name={}, trait_def_id={:?}, opt_input_types={:?})", + self_ty, m_name, trait_def_id, opt_input_types ); // Construct a trait-reference `self_ty : Trait<input_tys>` diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b2e4e7a981d..2320a29e6d8 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; @@ -1440,11 +1440,11 @@ impl Ord for TraitInfo { /// Retrieves all traits in this crate and any dependent crates. pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> { - tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect() + tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect() } /// Computes all traits in this crate and any dependent crates. -fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> { +fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { use hir::itemlikevisit; let mut traits = vec![]; @@ -1503,14 +1503,11 @@ fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> { handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id)); } - traits + tcx.arena.alloc_from_iter(traits) } pub fn provide(providers: &mut ty::query::Providers) { - providers.all_traits = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - &tcx.arena.alloc(compute_all_traits(tcx))[..] - } + providers.all_traits = compute_all_traits; } struct UsePlacementFinder<'tcx> { diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 994206bd419..ad7853b7cd0 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -105,7 +105,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirIdMap, ImplicitSelfKind, Node}; @@ -554,10 +554,8 @@ fn typeck_with_fallback<'tcx>( _ => false, }) => { - fcx.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span, - }) + // Inline assembly constants must be integers. + fcx.next_int_var() } _ => fallback(), }, @@ -1162,8 +1160,7 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {} } -fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) { - debug_assert!(crate_num == LOCAL_CRATE); +fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) { tcx.par_body_owners(|body_owner_def_id| { tcx.ensure().typeck(body_owner_def_id); }); @@ -1190,3 +1187,14 @@ fn fatally_break_rust(sess: &Session) { fn potentially_plural_count(count: usize, word: &str) -> String { format!("{} {}{}", count, word, pluralize!(count)) } + +fn has_expected_num_generic_args<'tcx>( + tcx: TyCtxt<'tcx>, + trait_did: Option<DefId>, + expected: usize, +) -> bool { + trait_did.map_or(true, |trait_did| { + let generics = tcx.generics_of(trait_did); + generics.count() == expected + if generics.has_self { 1 } else { 0 } + }) +} diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 567cb1a90d0..963436d05d8 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -1,7 +1,7 @@ //! Code related to processing overloaded binary and unary operators. use super::method::MethodCallee; -use super::FnCtxt; +use super::{has_expected_num_generic_args, FnCtxt}; use rustc_ast as ast; use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -795,6 +795,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty, op, opname, trait_did ); + // Catches cases like #83893, where a lang item is declared with the + // wrong number of generic arguments. Should have yielded an error + // elsewhere by now, but we have to catch it here so that we do not + // index `other_tys` out of bounds (if the lang item has too many + // generic arguments, `other_tys` is too short). + if !has_expected_num_generic_args( + self.tcx, + trait_did, + match op { + // Binary ops have a generic right-hand side, unary ops don't + Op::Binary(..) => 1, + Op::Unary(..) => 0, + }, + ) { + return Err(()); + } + let method = trait_did.and_then(|trait_did| { let opname = Ident::with_dummy_span(opname); self.lookup_method_in_trait(span, opname, trait_did, lhs_ty, Some(other_tys)) diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 5bd385107ca..a63aec07ad1 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -1,5 +1,5 @@ use crate::check::method::MethodCallee; -use crate::check::{FnCtxt, PlaceOp}; +use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp}; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; @@ -153,6 +153,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref), PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index), }; + + // If the lang item was declared incorrectly, stop here so that we don't + // run into an ICE (#83893). The error is reported where the lang item is + // declared. + if !has_expected_num_generic_args( + self.tcx, + imm_tr, + match op { + PlaceOp::Deref => 0, + PlaceOp::Index => 1, + }, + ) { + return None; + } + imm_tr.and_then(|trait_did| { self.lookup_method_in_trait( span, @@ -177,6 +192,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PlaceOp::Deref => (self.tcx.lang_items().deref_mut_trait(), sym::deref_mut), PlaceOp::Index => (self.tcx.lang_items().index_mut_trait(), sym::index_mut), }; + + // If the lang item was declared incorrectly, stop here so that we don't + // run into an ICE (#83893). The error is reported where the lang item is + // declared. + if !has_expected_num_generic_args( + self.tcx, + mut_tr, + match op { + PlaceOp::Deref => 0, + PlaceOp::Index => 1, + }, + ) { + return None; + } + mut_tr.and_then(|trait_did| { self.lookup_method_in_trait( span, diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 7a2b5b26ef4..71e222c560a 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -323,7 +323,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// InferBorrowKind results in a structure like this: /// - /// ``` + /// ```text /// { /// Place(base: hir_id_s, projections: [], ....) -> { /// capture_kind_expr: hir_id_L5, @@ -348,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ``` /// /// After the min capture analysis, we get: - /// ``` + /// ```text /// { /// hir_id_s -> [ /// Place(base: hir_id_s, projections: [], ....) -> { @@ -706,6 +706,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// enabled, **and** /// - It wasn't completely captured by the closure, **and** /// - One of the paths starting at this root variable, that is not captured needs Drop. + /// + /// This function only returns true for significant drops. A type is considerent to have a + /// significant drop if it's Drop implementation is not annotated by `rustc_insignificant_dtor`. fn compute_2229_migrations_for_drop( &self, closure_def_id: DefId, @@ -716,7 +719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id)); - if !ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { + if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) { return false; } @@ -835,11 +838,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// using list of `Projection` slices), it returns true if there is a path that is not /// captured starting at this root variable that implements Drop. /// - /// FIXME(project-rfc-2229#35): This should return true only for significant drops. - /// A drop is significant if it's implemented by the user or does - /// anything that will have any observable behavior (other than - /// freeing up memory). - /// /// The way this function works is at a given call it looks at type `base_path_ty` of some base /// path say P and then list of projection slices which represent the different captures moved /// into the closure starting off of P. @@ -895,7 +893,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// (Ty((w.p).x), [ &[] ]) (Ty((w.p).y), []) // IMP 2 /// | | /// v v - /// false NeedsDrop(Ty(w.p.y)) + /// false NeedsSignificantDrop(Ty(w.p.y)) /// | /// v /// true @@ -939,7 +937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { captured_by_move_projs: Vec<&[Projection<'tcx>]>, ) -> bool { let needs_drop = |ty: Ty<'tcx>| { - ty.needs_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) + ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) }; let is_drop_defined_for_ty = |ty: Ty<'tcx>| { diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index e1743a5dfc1..836bed2a156 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::TyCtxt; use rustc_session::lint; @@ -77,7 +77,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { // can always suggest removing (no matter which edition we are // in). let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx - .maybe_unused_extern_crates(LOCAL_CRATE) + .maybe_unused_extern_crates(()) .iter() .filter(|&&(def_id, _)| { // The `def_id` here actually was calculated during resolution (at least diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index cc592c7a260..51698437a30 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -9,16 +9,14 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::{self, CrateInherentImpls, TyCtxt}; use rustc_span::Span; /// On-demand query: yields a map containing all types mapped to their inherent impls. -pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateInherentImpls { - assert_eq!(crate_num, LOCAL_CRATE); - +pub fn crate_inherent_impls(tcx: TyCtxt<'_>, (): ()) -> CrateInherentImpls { let krate = tcx.hir().krate(); let mut collect = InherentCollect { tcx, impls_map: Default::default() }; krate.visit_all_item_likes(&mut collect); @@ -27,9 +25,9 @@ pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateInhere /// On-demand query: yields a vector of the inherent impls for a specific type. pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] { - assert!(ty_def_id.is_local()); + let ty_def_id = ty_def_id.expect_local(); - let crate_map = tcx.crate_inherent_impls(ty_def_id.krate); + let crate_map = tcx.crate_inherent_impls(()); match crate_map.inherent_impls.get(&ty_def_id) { Some(v) => &v[..], None => &[], @@ -364,7 +362,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { impl InherentCollect<'tcx> { fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) { - if def_id.is_local() { + if let Some(def_id) = def_id.as_local() { // Add the implementation to the mapping from implementation to base // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index c69389e7b43..f039790eca1 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -1,7 +1,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; @@ -9,8 +9,7 @@ use rustc_trait_selection::traits::{self, SkipLeakCheck}; use smallvec::SmallVec; use std::collections::hash_map::Entry; -pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) { - assert_eq!(crate_num, LOCAL_CRATE); +pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, (): ()) { let krate = tcx.hir().krate(); krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx }); } diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index f04782a1f44..03a9fe01795 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -6,7 +6,7 @@ // mappings. That mapping code resides here. use rustc_errors::struct_span_err; -use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::Span; @@ -203,8 +203,8 @@ pub fn check_coherence(tcx: TyCtxt<'_>) { tcx.sess.time("orphan_checking", || orphan::check(tcx)); // these queries are executed for side-effects (error reporting): - tcx.ensure().crate_inherent_impls(LOCAL_CRATE); - tcx.ensure().crate_inherent_impls_overlap_check(LOCAL_CRATE); + tcx.ensure().crate_inherent_impls(()); + tcx.ensure().crate_inherent_impls_overlap_check(()); } /// Checks whether an impl overlaps with the automatic `impl Trait for dyn Trait`. diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 4e07e52347a..47299722325 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -97,7 +97,7 @@ mod variance; use rustc_errors::{struct_span_err, ErrorReported}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_hir::{Node, CRATE_HIR_ID}; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; use rustc_infer::traits::TraitEngineExt as _; @@ -449,7 +449,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { } fn check_for_entry_fn(tcx: TyCtxt<'_>) { - match tcx.entry_fn(LOCAL_CRATE) { + match tcx.entry_fn(()) { Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id), Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), _ => {} @@ -510,7 +510,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { } }); - tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); + tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(())); check_unused::check_crate(tcx); check_for_entry_fn(tcx); diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_typeck/src/outlives/mod.rs index e94b8450bfd..d7eb31c2abe 100644 --- a/compiler/rustc_typeck/src/outlives/mod.rs +++ b/compiler/rustc_typeck/src/outlives/mod.rs @@ -1,6 +1,6 @@ use hir::Node; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt}; @@ -23,7 +23,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate match tcx.hir().get(id) { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { - let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE); + let crate_map = tcx.inferred_outlives_crate(()); let predicates = crate_map.predicates.get(&item_def_id).copied().unwrap_or(&[]); @@ -58,9 +58,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate } } -fn inferred_outlives_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CratePredicatesMap<'_> { - assert_eq!(crate_num, LOCAL_CRATE); - +fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { // Compute a map from each struct/enum/union S to the **explicit** // outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote. // Typically there won't be many of these, except in older code where diff --git a/compiler/rustc_typeck/src/variance/mod.rs b/compiler/rustc_typeck/src/variance/mod.rs index 1565efbb022..66fb9eb8693 100644 --- a/compiler/rustc_typeck/src/variance/mod.rs +++ b/compiler/rustc_typeck/src/variance/mod.rs @@ -6,7 +6,7 @@ use hir::Node; use rustc_arena::DroplessArena; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::DefId; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, TyCtxt}; @@ -30,8 +30,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { variances_of, crate_variances, ..*providers }; } -fn crate_variances(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateVariancesMap<'_> { - assert_eq!(crate_num, LOCAL_CRATE); +fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> { let arena = DroplessArena::default(); let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &arena); let constraints_cx = constraints::add_constraints_from_crate(terms_cx); @@ -79,6 +78,6 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { // Everything else must be inferred. - let crate_map = tcx.crate_variances(LOCAL_CRATE); + let crate_map = tcx.crate_variances(()); crate_map.variances.get(&item_def_id).copied().unwrap_or(&[]) } |
