diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index e4396a50a15e..fc31912283a7 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1948,7 +1948,7 @@ impl DummyAstNode for Item { span: Default::default(), tokens: Default::default(), }, - ident: Ident::empty(), + ident: Ident::dummy(), kind: ItemKind::ExternCrate(None), tokens: Default::default(), } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0e6b0bab082e..35541bb04bd7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -9,7 +9,6 @@ use rustc_errors::{DiagCtxtHandle, Diagnostic}; use rustc_feature::Features; use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId}; use rustc_session::Session; -use rustc_span::symbol::kw; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; @@ -338,7 +337,7 @@ impl<'sess> AttributeParser<'sess> { "expr in place where literal is expected (builtin attr parsing)", ); ast::MetaItemLit { - symbol: kw::Empty, + symbol: sym::dummy, suffix: None, kind: ast::LitKind::Err(guar), span: DUMMY_SP, diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index f0cce26f4e24..a8a1460591cf 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -12,7 +12,7 @@ use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, Norma use rustc_ast_pretty::pprust; use rustc_errors::DiagCtxtHandle; use rustc_hir::{self as hir, AttrPath}; -use rustc_span::symbol::{Ident, kw}; +use rustc_span::symbol::{Ident, kw, sym}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; pub struct SegmentIterator<'a> { @@ -360,7 +360,7 @@ fn expr_to_lit(dcx: DiagCtxtHandle<'_>, expr: &Expr, span: Span) -> MetaItemLit span, "expr in place where literal is expected (builtin attr parsing)", ); - MetaItemLit { symbol: kw::Empty, suffix: None, kind: LitKind::Err(guar), span } + MetaItemLit { symbol: sym::dummy, suffix: None, kind: LitKind::Err(guar), span } } } diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 8cb001391c52..0ea53627fe78 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -274,7 +274,7 @@ fn parse_tree<'a>( let msg = format!("expected identifier, found `{}`", pprust::token_to_string(token),); sess.dcx().span_err(token.span, msg); - TokenTree::MetaVar(token.span, Ident::empty()) + TokenTree::MetaVar(token.span, Ident::dummy()) } // There are no more tokens. Just return the `$` we already have. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 53f0194091cd..d4dfb9f29736 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -243,7 +243,7 @@ impl<'hir> PathSegment<'hir> { } pub fn invalid() -> Self { - Self::new(Ident::empty(), HirId::INVALID, Res::Err) + Self::new(Ident::dummy(), HirId::INVALID, Res::Err) } pub fn args(&self) -> &GenericArgs<'hir> { @@ -4332,16 +4332,6 @@ pub enum OwnerNode<'hir> { } impl<'hir> OwnerNode<'hir> { - pub fn ident(&self) -> Option { - match self { - OwnerNode::Item(Item { ident, .. }) - | OwnerNode::ForeignItem(ForeignItem { ident, .. }) - | OwnerNode::ImplItem(ImplItem { ident, .. }) - | OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident), - OwnerNode::Crate(..) | OwnerNode::Synthetic => None, - } - } - pub fn span(&self) -> Span { match self { OwnerNode::Item(Item { span, .. }) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 163d9a1b9d97..ae624fc253f2 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -553,24 +553,6 @@ impl<'a> State<'a> { self.word(";") } - fn print_item_type( - &mut self, - item: &hir::Item<'_>, - generics: &hir::Generics<'_>, - inner: impl Fn(&mut Self), - ) { - self.head("type"); - self.print_ident(item.ident); - self.print_generic_params(generics.params); - self.end(); // end the inner ibox - - self.print_where_clause(generics); - self.space(); - inner(self); - self.word(";"); - self.end(); // end the outer ibox - } - fn print_item(&mut self, item: &hir::Item<'_>) { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); @@ -683,10 +665,17 @@ impl<'a> State<'a> { self.end() } hir::ItemKind::TyAlias(ty, generics) => { - self.print_item_type(item, generics, |state| { - state.word_space("="); - state.print_type(ty); - }); + self.head("type"); + self.print_ident(item.ident); + self.print_generic_params(generics.params); + self.end(); // end the inner ibox + + self.print_where_clause(generics); + self.space(); + self.word_space("="); + self.print_type(ty); + self.word(";"); + self.end(); // end the outer ibox } hir::ItemKind::Enum(ref enum_definition, params) => { self.print_enum_def(enum_definition, params, item.ident.name, item.span); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 786e8b876a61..7e4026db738d 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2933,7 +2933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let guar = if field.name == kw::Empty { - self.dcx().span_delayed_bug(field.span, "field name with no name") + self.dcx().span_bug(field.span, "field name with no name") } else if self.method_exists_for_diagnostic( field, base_ty, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 36ad0ae1c301..da2d65794230 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -832,15 +832,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_missing_method = matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait(); - if item_name.name != kw::Empty { - self.report_method_error( - hir_id, - ty.normalized, - error, - Expectation::NoExpectation, - trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021 - ); - } + assert_ne!(item_name.name, kw::Empty); + self.report_method_error( + hir_id, + ty.normalized, + error, + Expectation::NoExpectation, + trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021 + ); result }); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 19ae3e3899c9..7e6973259feb 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -87,10 +87,10 @@ struct TopInfo<'tcx> { } #[derive(Copy, Clone)] -struct PatInfo<'a, 'tcx> { +struct PatInfo<'tcx> { binding_mode: ByRef, max_ref_mutbl: MutblCap, - top_info: &'a TopInfo<'tcx>, + top_info: TopInfo<'tcx>, decl_origin: Option>, /// The depth of current pattern @@ -303,11 +303,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { origin_expr: Option<&'tcx hir::Expr<'tcx>>, decl_origin: Option>, ) { - let info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id }; + let top_info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id }; let pat_info = PatInfo { binding_mode: ByRef::No, max_ref_mutbl: MutblCap::Mut, - top_info: &info, + top_info, decl_origin, current_depth: 0, }; @@ -320,7 +320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Outside of this module, `check_pat_top` should always be used. /// Conversely, inside this module, `check_pat_top` should never be used. #[instrument(level = "debug", skip(self, pat_info))] - fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'_, 'tcx>) { + fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) { let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; let path_res = match pat.kind { @@ -352,13 +352,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath, path_res.unwrap(), expected, - ti, + &pat_info.top_info, ); self.write_ty(*hir_id, ty); ty } - PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti), - PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), + PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info), + PatKind::Range(lhs, rhs, _) => { + self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info) + } PatKind::Binding(ba, var_id, ident, sub) => { self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info) } @@ -818,7 +820,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ident: Ident, sub: Option<&'tcx Pat<'tcx>>, expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info; @@ -914,12 +916,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local. - let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti); + let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, &ti); // If there are multiple arms, make sure they all agree on // what the type of the binding `x` ought to be. if var_id != pat.hir_id { - self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, ti); + self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, &ti); } if let Some(p) = sub { @@ -1149,7 +1151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { // Resolve the path and check the definition for errors. let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) { @@ -1164,7 +1166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Type-check the path. - let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info); + let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info); // Type-check subpatterns. match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) { @@ -1353,7 +1355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { subpats: &'tcx [Pat<'tcx>], ddpos: hir::DotDotPos, expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let on_error = |e| { @@ -1403,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); // Type-check the tuple struct pattern against the expected type. - let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info); + let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info); let had_err = diag.map_err(|diag| diag.emit()); // Type-check subpatterns. @@ -1610,7 +1612,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { elements: &'tcx [Pat<'tcx>], ddpos: hir::DotDotPos, expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let mut expected_len = elements.len(); @@ -1625,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span)); let element_tys = tcx.mk_type_list_from_iter(element_tys_iter); let pat_ty = Ty::new_tup(tcx, element_tys); - if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) { + if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, &pat_info.top_info) { // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported)); @@ -1648,7 +1650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant: &'tcx ty::VariantDef, fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx; @@ -2257,7 +2259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, inner: &'tcx Pat<'tcx>, expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; let (box_ty, inner_ty) = self @@ -2267,7 +2269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // think any errors can be introduced by using `demand::eqtype`. let inner_ty = self.next_ty_var(inner.span); let box_ty = Ty::new_box(tcx, inner_ty); - self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?; + self.demand_eqtype_pat(span, expected, box_ty, &pat_info.top_info)?; Ok((box_ty, inner_ty)) }) .unwrap_or_else(|guar| { @@ -2283,7 +2285,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, inner: &'tcx Pat<'tcx>, expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; // Register a `DerefPure` bound, which is required by all `deref!()` pats. @@ -2324,7 +2326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inner: &'tcx Pat<'tcx>, pat_mutbl: Mutability, mut expected: Ty<'tcx>, - mut pat_info: PatInfo<'_, 'tcx>, + mut pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; @@ -2482,7 +2484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat.span, expected, ref_ty, - pat_info.top_info, + &pat_info.top_info, ); // Look for a case like `fn foo(&foo: u32)` and suggest @@ -2605,7 +2607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { slice: Option<&'tcx Pat<'tcx>>, after: &'tcx [Pat<'tcx>], expected: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { let expected = self.try_structurally_resolve_type(span, expected); @@ -2767,7 +2769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, span: Span, expected_ty: Ty<'tcx>, - pat_info: PatInfo<'_, 'tcx>, + pat_info: PatInfo<'tcx>, ) -> ErrorGuaranteed { let PatInfo { top_info: ti, current_depth, .. } = pat_info; diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs index 0f4f885bb3ae..67ac805c2bfe 100644 --- a/compiler/rustc_index/src/slice.rs +++ b/compiler/rustc_index/src/slice.rs @@ -1,6 +1,7 @@ use std::fmt; use std::marker::PhantomData; use std::ops::{Index, IndexMut}; +use std::slice::GetDisjointMutError::*; use std::slice::{self, SliceIndex}; use crate::{Idx, IndexVec, IntoSliceIdx}; @@ -121,32 +122,36 @@ impl IndexSlice { /// Returns mutable references to two distinct elements, `a` and `b`. /// - /// Panics if `a == b`. + /// Panics if `a == b` or if some of them are out of bounds. #[inline] pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) { let (ai, bi) = (a.index(), b.index()); - assert!(ai != bi); - - if ai < bi { - let (c1, c2) = self.raw.split_at_mut(bi); - (&mut c1[ai], &mut c2[0]) - } else { - let (c2, c1) = self.pick2_mut(b, a); - (c1, c2) + + match self.raw.get_disjoint_mut([ai, bi]) { + Ok([a, b]) => (a, b), + Err(OverlappingIndices) => panic!("Indices {ai:?} and {bi:?} are not disjoint!"), + Err(IndexOutOfBounds) => { + panic!("Some indices among ({ai:?}, {bi:?}) are out of bounds") + } } } /// Returns mutable references to three distinct elements. /// - /// Panics if the elements are not distinct. + /// Panics if the elements are not distinct or if some of them are out of bounds. #[inline] pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) { let (ai, bi, ci) = (a.index(), b.index(), c.index()); - assert!(ai != bi && bi != ci && ci != ai); - let len = self.raw.len(); - assert!(ai < len && bi < len && ci < len); - let ptr = self.raw.as_mut_ptr(); - unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) } + + match self.raw.get_disjoint_mut([ai, bi, ci]) { + Ok([a, b, c]) => (a, b, c), + Err(OverlappingIndices) => { + panic!("Indices {ai:?}, {bi:?} and {ci:?} are not disjoint!") + } + Err(IndexOutOfBounds) => { + panic!("Some indices among ({ai:?}, {bi:?}, {ci:?}) are out of bounds") + } + } } #[inline] diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index cd4106ebf83a..017ae943e916 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -6,6 +6,7 @@ use std::cell::Cell; use std::slice; +use rustc_ast::BindingMode; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync; use rustc_data_structures::unord::UnordMap; @@ -14,6 +15,7 @@ use rustc_feature::Features; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_hir::{Pat, PatKind}; use rustc_middle::bug; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout}; @@ -890,7 +892,12 @@ impl<'tcx> LateContext<'tcx> { } && let Some(init) = match parent_node { hir::Node::Expr(expr) => Some(expr), - hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init, + hir::Node::LetStmt(hir::LetStmt { + init, + // Binding is immutable, init cannot be re-assigned + pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. }, + .. + }) => *init, _ => None, } { @@ -935,7 +942,12 @@ impl<'tcx> LateContext<'tcx> { } && let Some(init) = match parent_node { hir::Node::Expr(expr) => Some(expr), - hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init, + hir::Node::LetStmt(hir::LetStmt { + init, + // Binding is immutable, init cannot be re-assigned + pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. }, + .. + }) => *init, hir::Node::Item(item) => match item.kind { hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => { Some(self.tcx.hir_body(body_id).value) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e309f144b4f4..9e6cdfe59bba 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -646,7 +646,7 @@ impl<'a> Parser<'a> { let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?; - let item_kind = match ty_second { + let (of_trait, self_ty) = match ty_second { Some(ty_second) => { // impl Trait for Type if !has_for { @@ -679,31 +679,20 @@ impl<'a> Parser<'a> { }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; - ItemKind::Impl(Box::new(Impl { - safety, - polarity, - defaultness, - constness, - generics, - of_trait: Some(trait_ref), - self_ty: ty_second, - items: impl_items, - })) - } - None => { - // impl Type - ItemKind::Impl(Box::new(Impl { - safety, - polarity, - defaultness, - constness, - generics, - of_trait: None, - self_ty: ty_first, - items: impl_items, - })) + (Some(trait_ref), ty_second) } + None => (None, ty_first), // impl Type }; + let item_kind = ItemKind::Impl(Box::new(Impl { + safety, + polarity, + defaultness, + constness, + generics, + of_trait, + self_ty, + items: impl_items, + })); Ok((Ident::empty(), item_kind)) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5271d03a6f61..ff203b2938e0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -40,7 +40,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::hygiene::Transparency; -use rustc_span::{Ident, Span, Symbol, kw, sym}; +use rustc_span::{Ident, Span, Symbol, sym}; use tracing::debug; use {rustc_attr_parsing as attr, rustc_hir as hir}; @@ -935,8 +935,8 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { } // definition of the field - let ident = Ident::new(kw::Empty, use_ctxt); - let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1; + let ident = Ident::new(sym::dummy, use_ctxt); + let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id); !field.vis.is_accessible_from(def_id, self.tcx) } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e3405c89b79a..88d1126de1ae 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2266,7 +2266,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && !first.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. - path.insert(0, Segment::from_ident(Ident::empty())); + path.insert(0, Segment::from_ident(Ident::dummy())); } _ => return None, } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 718f23d761f0..8a8bec35d819 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -33,6 +33,15 @@ symbols! { // Special reserved identifiers used internally for elided lifetimes, // unnamed method parameters, crate root module, error recovery etc. // Matching predicates: `is_any_keyword`, `is_special`/`is_reserved` + // + // Notes about `kw::Empty`: + // - Its use can blur the lines between "empty symbol" and "no symbol". + // Using `Option` is preferable, where possible, because that + // is unambiguous. + // - For dummy symbols that are never used and absolutely must be + // present, it's better to use `sym::dummy` than `kw::Empty`, because + // it's clearer that it's intended as a dummy value, and more likely + // to be detected if it accidentally does get used. Empty: "", PathRoot: "{{root}}", DollarCrate: "$crate", @@ -834,6 +843,7 @@ symbols! { drop_types_in_const, dropck_eyepatch, dropck_parametricity, + dummy: "", // use this instead of `kw::Empty` for symbols that won't be used dummy_cgu_name, dylib, dyn_compatible_for_dispatch, @@ -2305,11 +2315,23 @@ impl Ident { Ident::new(name, DUMMY_SP) } + /// This is best avoided, because it blurs the lines between "empty + /// identifier" and "no identifier". Using `Option` is preferable, + /// where possible, because that is unambiguous. #[inline] pub fn empty() -> Ident { Ident::with_dummy_span(kw::Empty) } + // For dummy identifiers that are never used and absolutely must be + // present, it's better to use `Ident::dummy` than `Ident::Empty`, because + // it's clearer that it's intended as a dummy value, and more likely to be + // detected if it accidentally does get used. + #[inline] + pub fn dummy() -> Ident { + Ident::with_dummy_span(sym::dummy) + } + /// Maps a string to an identifier with a dummy span. pub fn from_str(string: &str) -> Ident { Ident::with_dummy_span(Symbol::intern(string)) diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index d4502be6ccfe..3fceada25104 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -24,7 +24,9 @@ use super::elaborate; use crate::infer::TyCtxtInferExt; pub use crate::traits::DynCompatibilityViolation; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{MethodViolationCode, Obligation, ObligationCause, util}; +use crate::traits::{ + MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util, +}; /// Returns the dyn-compatibility violations that affect HIR ty lowering. /// @@ -579,8 +581,8 @@ fn receiver_is_dispatchable<'tcx>( let unsized_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id); - // create a modified param env, with `Self: Unsize` and `U: Trait` added to caller bounds - // `U: ?Sized` is already implied here + // create a modified param env, with `Self: Unsize` and `U: Trait` (and all of + // its supertraits) added to caller bounds. `U: ?Sized` is already implied here. let param_env = { let param_env = tcx.param_env(method.def_id); @@ -598,10 +600,13 @@ fn receiver_is_dispatchable<'tcx>( ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx) }; - let caller_bounds = - param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]); - - ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds)) + normalize_param_env_or_error( + tcx, + ty::ParamEnv::new(tcx.mk_clauses_from_iter( + param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]), + )), + ObligationCause::dummy_with_span(tcx.def_span(method.def_id)), + ) }; // Receiver: DispatchFromDyn U]> diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index b764b8fa5d97..63828b482b9a 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -361,6 +361,74 @@ impl DerefMut for PeekMut<'_, T, A> { } impl<'a, T: Ord, A: Allocator> PeekMut<'a, T, A> { + /// Sifts the current element to its new position. + /// + /// Afterwards refers to the new element. Returns if the element changed. + /// + /// ## Examples + /// + /// The condition can be used to upper bound all elements in the heap. When only few elements + /// are affected, the heap's sort ensures this is faster than a reconstruction from the raw + /// element list and requires no additional allocation. + /// + /// ``` + /// #![feature(binary_heap_peek_mut_refresh)] + /// use std::collections::BinaryHeap; + /// + /// let mut heap: BinaryHeap = (0..128).collect(); + /// let mut peek = heap.peek_mut().unwrap(); + /// + /// loop { + /// *peek = 99; + /// + /// if !peek.refresh() { + /// break; + /// } + /// } + /// + /// // Post condition, this is now an upper bound. + /// assert!(*peek < 100); + /// ``` + /// + /// When the element remains the maximum after modification, the peek remains unchanged: + /// + /// ``` + /// #![feature(binary_heap_peek_mut_refresh)] + /// use std::collections::BinaryHeap; + /// + /// let mut heap: BinaryHeap = [1, 2, 3].into(); + /// let mut peek = heap.peek_mut().unwrap(); + /// + /// assert_eq!(*peek, 3); + /// *peek = 42; + /// + /// // When we refresh, the peek is updated to the new maximum. + /// assert!(!peek.refresh(), "42 is even larger than 3"); + /// assert_eq!(*peek, 42); + /// ``` + #[unstable(feature = "binary_heap_peek_mut_refresh", issue = "138355")] + #[must_use = "is equivalent to dropping and getting a new PeekMut except for return information"] + pub fn refresh(&mut self) -> bool { + // The length of the underlying heap is unchanged by sifting down. The value stored for leak + // amplification thus remains accurate. We erase the leak amplification firstly because the + // operation is then equivalent to constructing a new PeekMut and secondly this avoids any + // future complication where original_len being non-empty would be interpreted as the heap + // having been leak amplified instead of checking the heap itself. + if let Some(original_len) = self.original_len.take() { + // SAFETY: This is how many elements were in the Vec at the time of + // the BinaryHeap::peek_mut call. + unsafe { self.heap.data.set_len(original_len.get()) }; + + // The length of the heap did not change by sifting, upholding our own invariants. + + // SAFETY: PeekMut is only instantiated for non-empty heaps. + (unsafe { self.heap.sift_down(0) }) != 0 + } else { + // The element was not modified. + false + } + } + /// Removes the peeked value from the heap and returns it. #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")] pub fn pop(mut this: PeekMut<'a, T, A>) -> T { @@ -672,6 +740,8 @@ impl BinaryHeap { /// # Safety /// /// The caller must guarantee that `pos < self.len()`. + /// + /// Returns the new position of the element. unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize { // Take out the value at `pos` and create a hole. // SAFETY: The caller guarantees that pos < self.len() @@ -698,10 +768,12 @@ impl BinaryHeap { /// Take an element at `pos` and move it down the heap, /// while its children are larger. /// + /// Returns the new position of the element. + /// /// # Safety /// /// The caller must guarantee that `pos < end <= self.len()`. - unsafe fn sift_down_range(&mut self, pos: usize, end: usize) { + unsafe fn sift_down_range(&mut self, pos: usize, end: usize) -> usize { // SAFETY: The caller guarantees that pos < end <= self.len(). let mut hole = unsafe { Hole::new(&mut self.data, pos) }; let mut child = 2 * hole.pos() + 1; @@ -721,7 +793,7 @@ impl BinaryHeap { // SAFETY: child is now either the old child or the old child+1 // We already proven that both are < self.len() and != hole.pos() if hole.element() >= unsafe { hole.get(child) } { - return; + return hole.pos(); } // SAFETY: same as above. @@ -736,16 +808,18 @@ impl BinaryHeap { // child == 2 * hole.pos() + 1 != hole.pos(). unsafe { hole.move_to(child) }; } + + hole.pos() } /// # Safety /// /// The caller must guarantee that `pos < self.len()`. - unsafe fn sift_down(&mut self, pos: usize) { + unsafe fn sift_down(&mut self, pos: usize) -> usize { let len = self.len(); // SAFETY: pos < len is guaranteed by the caller and // obviously len = self.len() <= self.len(). - unsafe { self.sift_down_range(pos, len) }; + unsafe { self.sift_down_range(pos, len) } } /// Take an element at `pos` and move it all the way down the heap, diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 984c70955d7d..0caeb328811a 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -103,6 +103,7 @@ impl Step for Vendor { // Will read the libstd Cargo.toml // which uses the unstable `public-dependency` feature. cmd.env("RUSTC_BOOTSTRAP", "1"); + cmd.env("RUSTC", &builder.initial_rustc); cmd.current_dir(self.root_dir).arg(&self.output_dir); diff --git a/src/doc/book b/src/doc/book index 4a01a9182496..81a976a237f8 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 4a01a9182496f807aaa5f72d93a25ce18bcbe105 +Subproject commit 81a976a237f84b8392c4ce1bd5fd076eb757a2eb diff --git a/src/doc/edition-guide b/src/doc/edition-guide index daa4b763cd84..1e27e5e6d513 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit daa4b763cd848f986813b5cf8069e1649f7147af +Subproject commit 1e27e5e6d5133ae4612f5cc195c15fc8d51b1c9c diff --git a/src/doc/nomicon b/src/doc/nomicon index 8f5c7322b65d..b4448fa406a6 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 8f5c7322b65d079aa5b242eb10d89a98e12471e1 +Subproject commit b4448fa406a6dccde62d1e2f34f70fc51814cdcc diff --git a/src/doc/reference b/src/doc/reference index 615b4cec60c2..dda31c85f2ef 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 615b4cec60c269cfc105d511c93287620032d5b0 +Subproject commit dda31c85f2ef2e5d2f0f2f643c9231690a30a626 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 66543bbc5b7d..6f69823c28ae 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 66543bbc5b7dbd4e679092c07ae06ba6c73fd912 +Subproject commit 6f69823c28ae8d929d6c815181c73d3e99ef16d3 diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs index 7421e08c8988..3abe84730526 100644 --- a/tests/ui/associated-types/issue-59324.rs +++ b/tests/ui/associated-types/issue-59324.rs @@ -15,6 +15,7 @@ pub trait ThriftService: { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied + //~| ERROR the trait bound `Bug: Foo` is not satisfied &self, ) -> Self::AssocType; //~^ ERROR the trait bound `Bug: Foo` is not satisfied diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr index dc8f9cfe895b..f5e696b7ac1c 100644 --- a/tests/ui/associated-types/issue-59324.stderr +++ b/tests/ui/associated-types/issue-59324.stderr @@ -32,6 +32,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied | LL | / fn get_service( LL | | +LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` @@ -41,8 +42,18 @@ help: consider further restricting type parameter `Bug` with trait `Foo` LL | pub trait ThriftService: | +++++ +error[E0277]: the trait bound `Bug: Foo` is not satisfied + --> $DIR/issue-59324.rs:16:5 + | +LL | / fn get_service( +LL | | +LL | | +LL | | &self, +LL | | ) -> Self::AssocType; + | |_________________________^ the trait `Foo` is not implemented for `Bug` + error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:24:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` @@ -54,7 +65,7 @@ LL | pub trait Foo: NotFoo { | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:19:10 + --> $DIR/issue-59324.rs:20:10 | LL | ) -> Self::AssocType; | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` @@ -65,7 +76,7 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:24:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` @@ -78,7 +89,7 @@ LL | pub trait Foo: NotFoo { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time - --> $DIR/issue-59324.rs:23:29 + --> $DIR/issue-59324.rs:24:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -95,6 +106,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn with_factory(factory: &dyn ThriftService<()>) {} | + -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs index 87a906761c07..cbc1d8e90459 100644 --- a/tests/ui/lint/invalid_from_utf8.rs +++ b/tests/ui/lint/invalid_from_utf8.rs @@ -128,18 +128,21 @@ pub fn from_utf8() { } pub fn from_utf8_with_indirections() { - let mut a = [99, 108, 130, 105, 112, 112, 121]; - std::str::from_utf8_mut(&mut a); - //~^ WARN calls to `std::str::from_utf8_mut` - str::from_utf8_mut(&mut a); - //~^ WARN calls to `str::from_utf8_mut` - let mut b = &mut a; - let mut c = b; - std::str::from_utf8_mut(c); - //~^ WARN calls to `std::str::from_utf8_mut` - str::from_utf8_mut(c); - //~^ WARN calls to `str::from_utf8_mut` - let mut c = &[99, 108, 130, 105, 112, 112, 121]; + // NOTE: We used to lint on the patterns below, but due to the + // binding being mutable it could be changed between the + // declaration and the call and that would have created a + // false-positive, so until we can reliably avoid those false + // postive we don't lint on them. Example of FP below. + // + // let mut a = [99, 108, 130, 105, 112, 112, 121]; + // std::str::from_utf8_mut(&mut a); + // str::from_utf8_mut(&mut a); + // let mut b = &mut a; + // let mut c = b; + // std::str::from_utf8_mut(c); + // str::from_utf8_mut(c); + + let c = &[99, 108, 130, 105, 112, 112, 121]; std::str::from_utf8(c); //~^ WARN calls to `std::str::from_utf8` str::from_utf8(c); @@ -164,6 +167,20 @@ pub fn from_utf8_with_indirections() { //~^ WARN calls to `std::str::from_utf8` str::from_utf8(INVALID_4); //~^ WARN calls to `str::from_utf8` + + let mut a = [99, 108, 130, 105, 112, 112, 121]; // invalid + loop { + a = [99, 108, 130, 105, 112, 112, 121]; // still invalid, but too complex + break; + } + std::str::from_utf8_mut(&mut a); + + let mut a = [99, 108, 130, 105, 112, 112]; // invalid + loop { + a = *b"clippy"; // valid + break; + } + std::str::from_utf8_mut(&mut a); } fn main() {} diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr index 3cd4d227fc27..26bee5c40386 100644 --- a/tests/ui/lint/invalid_from_utf8.stderr +++ b/tests/ui/lint/invalid_from_utf8.stderr @@ -202,60 +202,25 @@ LL | str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); | | | the literal was valid UTF-8 up to the 2 bytes -warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:132:5 - | -LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; - | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes -LL | std::str::from_utf8_mut(&mut a); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: calls to `str::from_utf8_mut` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:134:5 - | -LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; - | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes -... -LL | str::from_utf8_mut(&mut a); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:138:5 - | -LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; - | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes -... -LL | std::str::from_utf8_mut(c); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: calls to `str::from_utf8_mut` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:140:5 - | -LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; - | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes -... -LL | str::from_utf8_mut(c); - | ^^^^^^^^^^^^^^^^^^^^^ - warning: calls to `std::str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:143:5 + --> $DIR/invalid_from_utf8.rs:146:5 | -LL | let mut c = &[99, 108, 130, 105, 112, 112, 121]; - | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | let c = &[99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes LL | std::str::from_utf8(c); | ^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:145:5 + --> $DIR/invalid_from_utf8.rs:148:5 | -LL | let mut c = &[99, 108, 130, 105, 112, 112, 121]; - | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes +LL | let c = &[99, 108, 130, 105, 112, 112, 121]; + | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes ... LL | str::from_utf8(c); | ^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:148:5 + --> $DIR/invalid_from_utf8.rs:151:5 | LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -263,7 +228,7 @@ LL | std::str::from_utf8(&INVALID_1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:150:5 + --> $DIR/invalid_from_utf8.rs:153:5 | LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -272,7 +237,7 @@ LL | str::from_utf8(&INVALID_1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:153:5 + --> $DIR/invalid_from_utf8.rs:156:5 | LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -280,7 +245,7 @@ LL | std::str::from_utf8(&INVALID_2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:155:5 + --> $DIR/invalid_from_utf8.rs:158:5 | LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -289,7 +254,7 @@ LL | str::from_utf8(&INVALID_2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:158:5 + --> $DIR/invalid_from_utf8.rs:161:5 | LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -297,7 +262,7 @@ LL | std::str::from_utf8(INVALID_3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:160:5 + --> $DIR/invalid_from_utf8.rs:163:5 | LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -306,7 +271,7 @@ LL | str::from_utf8(INVALID_3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:163:5 + --> $DIR/invalid_from_utf8.rs:166:5 | LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -314,7 +279,7 @@ LL | std::str::from_utf8(INVALID_4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `str::from_utf8` with an invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:165:5 + --> $DIR/invalid_from_utf8.rs:168:5 | LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -322,5 +287,5 @@ LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 12 LL | str::from_utf8(INVALID_4); | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: 38 warnings emitted +warning: 34 warnings emitted diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs new file mode 100644 index 000000000000..55c070eb0368 --- /dev/null +++ b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs @@ -0,0 +1,38 @@ +//@ check-pass + +#![feature(derive_coerce_pointee)] +#![feature(arbitrary_self_types)] + +use std::ops::Deref; +use std::marker::CoercePointee; +use std::sync::Arc; + +trait MyTrait {} + +#[derive(CoercePointee)] +#[repr(transparent)] +struct MyArc>(Arc); + +impl> Deref for MyArc { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +// This is variant on "tests/ui/self/dyn-dispatch-requires-supertrait.rs" but with +// a supertrait that requires normalization to match the pred in the old solver. +trait MyOtherTrait: MyTrait<::Assoc> { + fn foo(self: MyArc); +} + +fn test(_: MyArc) {} + +fn main() {} diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait.rs b/tests/ui/self/dyn-dispatch-requires-supertrait.rs new file mode 100644 index 000000000000..f2661c406fef --- /dev/null +++ b/tests/ui/self/dyn-dispatch-requires-supertrait.rs @@ -0,0 +1,38 @@ +//@ check-pass + +#![feature(derive_coerce_pointee)] +#![feature(arbitrary_self_types)] + +use std::ops::Deref; +use std::marker::CoercePointee; +use std::sync::Arc; + +trait MyTrait {} + +#[derive(CoercePointee)] +#[repr(transparent)] +struct MyArc +where + T: MyTrait + ?Sized, +{ + inner: Arc +} + +impl Deref for MyArc { + type Target = T; + fn deref(&self) -> &T { + &self.inner + } +} + +// Proving that `MyArc` is dyn-dispatchable requires proving `MyArc` implements +// `DispatchFromDyn>`. The `DispatchFromDyn` impl that is generated from the +// `CoercePointee` implementation requires the pointee impls `MyTrait`, but previously we +// were only assuming the pointee impl'd `MyOtherTrait`. Elaboration comes to the rescue here. +trait MyOtherTrait: MyTrait { + fn foo(self: MyArc); +} + +fn test(_: MyArc) {} + +fn main() {}