From cdc730457e9030feaf8c4376a668a9ef61c7f189 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 6 Mar 2020 11:20:27 +0100 Subject: [PATCH 01/12] Compute the correct layout for variants of uninhabited enums and readd a long lost assertion This reverts part of commit 9712fa405944cb8d5416556ac4b1f26365a10658. --- src/librustc/ty/layout.rs | 14 +++++++++++--- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/place.rs | 8 -------- src/librustc_target/abi/mod.rs | 6 +++++- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dedb3035cedb3..f616d81603775 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -782,8 +782,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { present_first @ Some(_) => present_first, // Uninhabited because it has no variants, or only absent ones. None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)), - // if it's a struct, still compute a layout so that we can still compute the - // field offsets + // If it's a struct, still compute a layout so that we can still compute the + // field offsets. None => Some(VariantIdx::new(0)), }; @@ -1990,7 +1990,15 @@ where { fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> { let details = match this.variants { - Variants::Single { index } if index == variant_index => this.details, + Variants::Single { index } + // If all variants but one are uninhabited, the variant layout is the enum layout. + if index == variant_index && + // Don't confuse variants of uninhabited enums with the enum itself. + // For more details see https://github.com/rust-lang/rust/issues/69763. + this.fields != FieldPlacement::Union(0) => + { + this.details + } Variants::Single { index } => { // Deny calling for_variant more than once for non-Single enums. diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 22b1a7b7137d9..5d035bbeb27c7 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -356,7 +356,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let base = match op.try_as_mplace(self) { Ok(mplace) => { - // The easy case + // We can reuse the mplace field computation logic for indirect operands let field = self.mplace_field(mplace, field)?; return Ok(field.into()); } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index a4815b9696ebb..856c654980ab7 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -410,14 +410,6 @@ where stride * field } layout::FieldPlacement::Union(count) => { - // This is a narrow bug-fix for rust-lang/rust#69191: if we are - // trying to access absent field of uninhabited variant, then - // signal UB (but don't ICE the compiler). - // FIXME temporary hack to work around incoherence between - // layout computation and MIR building - if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited { - throw_ub!(Unreachable); - } assert!( field < count as u64, "Tried to access field {} of union {:#?} with {} fields", diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 2f8bbd66c322b..681326b0f150a 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -660,7 +660,11 @@ impl FieldPlacement { pub fn offset(&self, i: usize) -> Size { match *self { - FieldPlacement::Union(_) => Size::ZERO, + FieldPlacement::Union(count) => { + assert!(i < count, + "Tried to access field {} of union with {} fields", i, count); + Size::ZERO + }, FieldPlacement::Array { stride, count } => { let i = i as u64; assert!(i < count); From ec88ffa38cee51fa7290aa6c99d928ffe346ca6c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 11 Mar 2020 13:57:54 +0100 Subject: [PATCH 02/12] Comment nits Co-Authored-By: Ralf Jung --- src/librustc_mir/interpret/operand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 5d035bbeb27c7..07c0f76e03a7e 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -356,7 +356,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let base = match op.try_as_mplace(self) { Ok(mplace) => { - // We can reuse the mplace field computation logic for indirect operands + // We can reuse the mplace field computation logic for indirect operands. let field = self.mplace_field(mplace, field)?; return Ok(field.into()); } From 74608c7f206171cb72c020a03800b2d9035a35fa Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 11 Mar 2020 14:31:07 +0100 Subject: [PATCH 03/12] Rustfmt and adjust capitalization --- src/librustc_target/abi/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 681326b0f150a..afa30e7e632a7 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -661,10 +661,9 @@ impl FieldPlacement { pub fn offset(&self, i: usize) -> Size { match *self { FieldPlacement::Union(count) => { - assert!(i < count, - "Tried to access field {} of union with {} fields", i, count); + assert!(i < count, "tried to access field {} of union with {} fields", i, count); Size::ZERO - }, + } FieldPlacement::Array { stride, count } => { let i = i as u64; assert!(i < count); From 71ebc6182012d80e076e4aaa03e0dbe44132fcbf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 18:39:16 +0300 Subject: [PATCH 04/12] resolve: Simplify `fn report_privacy_error` by factoring out `fn ctor_fields_span` into a separate function --- src/librustc_resolve/diagnostics.rs | 67 +++++++++++++---------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 47a05ec90d42f..edbb2db3868d4 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -916,51 +916,46 @@ impl<'a> Resolver<'a> { err.emit(); } - crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { - let PrivacyError { ident, binding, .. } = *privacy_error; - let session = &self.session; - let mk_struct_span_error = |is_constructor| { - let mut descr = binding.res().descr().to_string(); - if is_constructor { - descr += " constructor"; - } - if binding.is_import() { - descr += " import"; - } - - let mut err = - struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident); - - err.span_label(ident.span, &format!("this {} is private", descr)); - err.span_note( - session.source_map().def_span(binding.span), - &format!("the {} `{}` is defined here", descr, ident), - ); - - err - }; - - let mut err = if let NameBindingKind::Res( + /// If the binding refers to a tuple struct constructor with fields, + /// returns the span of its fields. + fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option { + if let NameBindingKind::Res( Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _, ) = binding.kind { let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor"); if let Some(fields) = self.field_names.get(&def_id) { - let mut err = mk_struct_span_error(true); let first_field = fields.first().expect("empty field list in the map"); - err.span_label( - fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), - "a constructor is private if any of the fields is private", - ); - err - } else { - mk_struct_span_error(false) + return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span))); } - } else { - mk_struct_span_error(false) - }; + } + None + } + + crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { + let PrivacyError { ident, binding, .. } = *privacy_error; + + let ctor_fields_span = self.ctor_fields_span(binding); + let mut descr = binding.res().descr().to_string(); + if ctor_fields_span.is_some() { + descr += " constructor"; + } + if binding.is_import() { + descr += " import"; + } + let mut err = + struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident); + err.span_label(ident.span, &format!("this {} is private", descr)); + if let Some(span) = ctor_fields_span { + err.span_label(span, "a constructor is private if any of the fields is private"); + } + + err.span_note( + self.session.source_map().def_span(binding.span), + &format!("the {} `{}` is defined here", descr, ident), + ); err.emit(); } } From 580c6a29d47a9cd786c89df98d97e6de13f49291 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 21:18:29 +0300 Subject: [PATCH 05/12] resolve: Print import chains on privacy errors --- src/librustc_resolve/diagnostics.rs | 61 +++++++++++++++---- src/test/ui/imports/issue-55884-2.stderr | 17 +++++- src/test/ui/imports/reexports.stderr | 14 ++++- src/test/ui/privacy/privacy2.stderr | 7 ++- .../shadowed/shadowed-use-visibility.stderr | 14 ++++- 5 files changed, 95 insertions(+), 18 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index edbb2db3868d4..063c62ad9aac7 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1,4 +1,5 @@ use std::cmp::Reverse; +use std::ptr; use log::debug; use rustc::bug; @@ -936,15 +937,17 @@ impl<'a> Resolver<'a> { crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { let PrivacyError { ident, binding, .. } = *privacy_error; + let res = binding.res(); let ctor_fields_span = self.ctor_fields_span(binding); - let mut descr = binding.res().descr().to_string(); - if ctor_fields_span.is_some() { - descr += " constructor"; - } - if binding.is_import() { - descr += " import"; - } - + let plain_descr = res.descr().to_string(); + let nonimport_descr = + if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr }; + let import_descr = nonimport_descr.clone() + " import"; + let get_descr = + |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; + + // Print the primary message. + let descr = get_descr(binding); let mut err = struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident); err.span_label(ident.span, &format!("this {} is private", descr)); @@ -952,10 +955,44 @@ impl<'a> Resolver<'a> { err.span_label(span, "a constructor is private if any of the fields is private"); } - err.span_note( - self.session.source_map().def_span(binding.span), - &format!("the {} `{}` is defined here", descr, ident), - ); + // Print the whole import chain to make it easier to see what happens. + let first_binding = binding; + let mut next_binding = Some(binding); + let mut next_ident = ident; + while let Some(binding) = next_binding { + let name = next_ident; + next_binding = match binding.kind { + _ if res == Res::Err => None, + NameBindingKind::Import { binding, import, .. } => match import.kind { + _ if binding.span.is_dummy() => None, + ImportKind::Single { source, .. } => { + next_ident = source; + Some(binding) + } + ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding), + ImportKind::ExternCrate { .. } => None, + }, + _ => None, + }; + + let first = ptr::eq(binding, first_binding); + let descr = get_descr(binding); + let msg = format!( + "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", + and_refers_to = if first { "" } else { "...and refers to " }, + item = descr, + name = name, + which = if first { "" } else { " which" }, + dots = if next_binding.is_some() { "..." } else { "" }, + ); + let def_span = self.session.source_map().def_span(binding.span); + let mut note_span = MultiSpan::from_span(def_span); + if !first && next_binding.is_none() && binding.vis == ty::Visibility::Public { + note_span.push_span_label(def_span, "consider importing it directly".into()); + } + err.span_note(note_span, &msg); + } + err.emit(); } } diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr index f16d2adb3656e..3eee7118e5a22 100644 --- a/src/test/ui/imports/issue-55884-2.stderr +++ b/src/test/ui/imports/issue-55884-2.stderr @@ -4,11 +4,26 @@ error[E0603]: struct import `ParseOptions` is private LL | pub use parser::ParseOptions; | ^^^^^^^^^^^^ this struct import is private | -note: the struct import `ParseOptions` is defined here +note: the struct import `ParseOptions` is defined here... --> $DIR/issue-55884-2.rs:9:9 | LL | use ParseOptions; | ^^^^^^^^^^^^ +note: ...and refers to the struct import `ParseOptions` which is defined here... + --> $DIR/issue-55884-2.rs:12:9 + | +LL | pub use parser::ParseOptions; + | ^^^^^^^^^^^^^^^^^^^^ +note: ...and refers to the struct import `ParseOptions` which is defined here... + --> $DIR/issue-55884-2.rs:6:13 + | +LL | pub use options::*; + | ^^^^^^^^^^ +note: ...and refers to the struct `ParseOptions` which is defined here + --> $DIR/issue-55884-2.rs:2:5 + | +LL | pub struct ParseOptions {} + | ^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly error: aborting due to previous error diff --git a/src/test/ui/imports/reexports.stderr b/src/test/ui/imports/reexports.stderr index 7b0d63574ec8e..d63fbc7ec6781 100644 --- a/src/test/ui/imports/reexports.stderr +++ b/src/test/ui/imports/reexports.stderr @@ -16,11 +16,16 @@ error[E0603]: module import `foo` is private LL | use b::a::foo::S; | ^^^ this module import is private | -note: the module import `foo` is defined here +note: the module import `foo` is defined here... --> $DIR/reexports.rs:21:17 | LL | pub use super::foo; // This is OK since the value `foo` is visible enough. | ^^^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/reexports.rs:16:5 + | +LL | mod foo { + | ^^^^^^^ error[E0603]: module import `foo` is private --> $DIR/reexports.rs:34:15 @@ -28,11 +33,16 @@ error[E0603]: module import `foo` is private LL | use b::b::foo::S as T; | ^^^ this module import is private | -note: the module import `foo` is defined here +note: the module import `foo` is defined here... --> $DIR/reexports.rs:26:17 | LL | pub use super::*; // This is also OK since the value `foo` is visible enough. | ^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/reexports.rs:16:5 + | +LL | mod foo { + | ^^^^^^^ warning: glob import doesn't reexport anything because no candidate is public enough --> $DIR/reexports.rs:9:17 diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index 719dc27ccf4d6..b10c3a5265971 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -10,11 +10,16 @@ error[E0603]: function import `foo` is private LL | use bar::glob::foo; | ^^^ this function import is private | -note: the function import `foo` is defined here +note: the function import `foo` is defined here... --> $DIR/privacy2.rs:10:13 | LL | use foo; | ^^^ +note: ...and refers to the function `foo` which is defined here + --> $DIR/privacy2.rs:14:1 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ consider importing it directly error: requires `sized` lang_item diff --git a/src/test/ui/shadowed/shadowed-use-visibility.stderr b/src/test/ui/shadowed/shadowed-use-visibility.stderr index cd8ec13794c6f..2244f3a46b266 100644 --- a/src/test/ui/shadowed/shadowed-use-visibility.stderr +++ b/src/test/ui/shadowed/shadowed-use-visibility.stderr @@ -4,11 +4,16 @@ error[E0603]: module import `bar` is private LL | use foo::bar::f as g; | ^^^ this module import is private | -note: the module import `bar` is defined here +note: the module import `bar` is defined here... --> $DIR/shadowed-use-visibility.rs:4:9 | LL | use foo as bar; | ^^^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/shadowed-use-visibility.rs:1:1 + | +LL | mod foo { + | ^^^^^^^ error[E0603]: module import `f` is private --> $DIR/shadowed-use-visibility.rs:15:10 @@ -16,11 +21,16 @@ error[E0603]: module import `f` is private LL | use bar::f::f; | ^ this module import is private | -note: the module import `f` is defined here +note: the module import `f` is defined here... --> $DIR/shadowed-use-visibility.rs:11:9 | LL | use foo as f; | ^^^^^^^^ +note: ...and refers to the module `foo` which is defined here + --> $DIR/shadowed-use-visibility.rs:1:1 + | +LL | mod foo { + | ^^^^^^^ error: aborting due to 2 previous errors From afa940b900c2003228ea7f5d9f8d78906d84c135 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Wed, 11 Mar 2020 19:18:22 +0100 Subject: [PATCH 06/12] Update the mir inline costs handle that when mir is lowered to llvm-ir more code is generated. landingpads generates 10 llvm-ir instructions and resume 9 llvm-ir instructions. --- src/librustc_mir/transform/inline.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index b6802505df73f..7cdebf6267075 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -25,6 +25,8 @@ const HINT_THRESHOLD: usize = 100; const INSTR_COST: usize = 5; const CALL_PENALTY: usize = 25; +const LANDINGPAD_PENALTY: usize = 50; +const RESUME_PENALTY: usize = 45; const UNKNOWN_SIZE_COST: usize = 10; @@ -328,6 +330,7 @@ impl Inliner<'tcx> { if ty.needs_drop(tcx, param_env) { cost += CALL_PENALTY; if let Some(unwind) = unwind { + cost += LANDINGPAD_PENALTY; work_list.push(unwind); } } else { @@ -343,7 +346,7 @@ impl Inliner<'tcx> { threshold = 0; } - TerminatorKind::Call { func: Operand::Constant(ref f), .. } => { + TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => { if let ty::FnDef(def_id, _) = f.literal.ty.kind { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); @@ -352,9 +355,21 @@ impl Inliner<'tcx> { } else { cost += CALL_PENALTY; } + } else { + cost += CALL_PENALTY; + } + if cleanup.is_some() { + cost += LANDINGPAD_PENALTY; + } + } + TerminatorKind::Assert { cleanup, .. } => { + cost += CALL_PENALTY; + + if cleanup.is_some() { + cost += LANDINGPAD_PENALTY; } } - TerminatorKind::Assert { .. } => cost += CALL_PENALTY, + TerminatorKind::Resume => cost += RESUME_PENALTY, _ => cost += INSTR_COST, } From f4083c6455ad47e0369013dba7eb716eb00223eb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 11 Mar 2020 21:17:23 +0300 Subject: [PATCH 07/12] Add the "consider importing it directly" label to public imports as well --- src/librustc_resolve/diagnostics.rs | 2 +- src/test/ui/imports/issue-55884-2.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 063c62ad9aac7..b00c7473bace3 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -987,7 +987,7 @@ impl<'a> Resolver<'a> { ); let def_span = self.session.source_map().def_span(binding.span); let mut note_span = MultiSpan::from_span(def_span); - if !first && next_binding.is_none() && binding.vis == ty::Visibility::Public { + if !first && binding.vis == ty::Visibility::Public { note_span.push_span_label(def_span, "consider importing it directly".into()); } err.span_note(note_span, &msg); diff --git a/src/test/ui/imports/issue-55884-2.stderr b/src/test/ui/imports/issue-55884-2.stderr index 3eee7118e5a22..490c08446b5a8 100644 --- a/src/test/ui/imports/issue-55884-2.stderr +++ b/src/test/ui/imports/issue-55884-2.stderr @@ -13,12 +13,12 @@ note: ...and refers to the struct import `ParseOptions` which is defined here... --> $DIR/issue-55884-2.rs:12:9 | LL | pub use parser::ParseOptions; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ consider importing it directly note: ...and refers to the struct import `ParseOptions` which is defined here... --> $DIR/issue-55884-2.rs:6:13 | LL | pub use options::*; - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider importing it directly note: ...and refers to the struct `ParseOptions` which is defined here --> $DIR/issue-55884-2.rs:2:5 | From f4eb6ed6b407bcbbd7311a2983ff661b2cd15393 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 11 Mar 2020 20:34:57 +0000 Subject: [PATCH 08/12] Ensure HAS_FREE_LOCAL_NAMES is set for ReFree --- src/librustc/ty/mod.rs | 27 +++++++++++++++------------ src/librustc/ty/sty.rs | 28 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7bcd63b965534..7df235b3cc1d4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -554,24 +554,26 @@ bitflags! { /// Does this have [ConstKind::Placeholder]? const HAS_CT_PLACEHOLDER = 1 << 8; + /// `true` if there are "names" of regions and so forth + /// that are local to a particular fn/inferctxt + const HAS_FREE_LOCAL_REGIONS = 1 << 9; + /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_RE_PARAM.bits | TypeFlags::HAS_CT_PARAM.bits | TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_RE_INFER.bits | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_RE_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits; + | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; /// Does this have [Projection] or [UnnormalizedProjection]? - const HAS_TY_PROJECTION = 1 << 9; + const HAS_TY_PROJECTION = 1 << 10; /// Does this have [Opaque]? - const HAS_TY_OPAQUE = 1 << 10; + const HAS_TY_OPAQUE = 1 << 11; /// Does this have [ConstKind::Unevaluated]? - const HAS_CT_PROJECTION = 1 << 11; + const HAS_CT_PROJECTION = 1 << 12; /// Could this type be normalized further? const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits @@ -580,21 +582,21 @@ bitflags! { /// Present if the type belongs in a local type context. /// Set for placeholders and inference variables that are not "Fresh". - const KEEP_IN_LOCAL_TCX = 1 << 12; + const KEEP_IN_LOCAL_TCX = 1 << 13; /// Is an error type reachable? - const HAS_TY_ERR = 1 << 13; + const HAS_TY_ERR = 1 << 14; /// Does this have any region that "appears free" in the type? /// Basically anything but [ReLateBound] and [ReErased]. - const HAS_FREE_REGIONS = 1 << 14; + const HAS_FREE_REGIONS = 1 << 15; /// Does this have any [ReLateBound] regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 15; + const HAS_RE_LATE_BOUND = 1 << 16; /// Does this have any [ReErased] regions? - const HAS_RE_ERASED = 1 << 16; + const HAS_RE_ERASED = 1 << 17; /// Flags representing the nominal content of a type, /// computed by FlagsComputation. If you add a new nominal @@ -608,6 +610,7 @@ bitflags! { | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_RE_PLACEHOLDER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits | TypeFlags::HAS_TY_PROJECTION.bits | TypeFlags::HAS_TY_OPAQUE.bits | TypeFlags::HAS_CT_PROJECTION.bits diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 47bf7822b1f55..649381db7cace 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1743,42 +1743,42 @@ impl RegionKind { } } - pub fn keep_in_local_tcx(&self) -> bool { - if let ty::ReVar(..) = self { true } else { false } - } - pub fn type_flags(&self) -> TypeFlags { let mut flags = TypeFlags::empty(); - if self.keep_in_local_tcx() { - flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; - } - match *self { ty::ReVar(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; + flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; } ty::RePlaceholder(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } - ty::ReLateBound(..) => { - flags = flags | TypeFlags::HAS_RE_LATE_BOUND; - } ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PARAM; } - ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => { + ty::ReFree { .. } | ty::ReScope { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; } - ty::ReErased => { - flags = flags | TypeFlags::HAS_RE_ERASED; + ty::ReEmpty(_) | ty::ReStatic => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; } ty::ReClosureBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } + ty::ReLateBound(..) => { + flags = flags | TypeFlags::HAS_RE_LATE_BOUND; + } + ty::ReErased => { + flags = flags | TypeFlags::HAS_RE_ERASED; + } } debug!("type_flags({:?}) = {:?}", self, flags); From e80cb2032cac39db2226ba940fad05b5adb17e62 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 15:28:17 +0300 Subject: [PATCH 09/12] resolve: Fix regression in resolution of raw keywords in paths --- src/librustc_resolve/lib.rs | 5 +---- src/test/rustdoc-ui/issue-61732.rs | 2 +- src/test/rustdoc-ui/issue-61732.stderr | 8 ++++---- .../keyword/extern/keyword-extern-as-identifier-use.rs | 1 + .../extern/keyword-extern-as-identifier-use.stderr | 9 ++++++++- src/test/ui/resolve/raw-ident-in-path.rs | 5 +++++ src/test/ui/resolve/raw-ident-in-path.stderr | 9 +++++++++ 7 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/resolve/raw-ident-in-path.rs create mode 100644 src/test/ui/resolve/raw-ident-in-path.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 948b86225f38b..02ac560093d04 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2183,11 +2183,8 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, )), ) - } else if !ident.is_reserved() { - (format!("maybe a missing crate `{}`?", ident), None) } else { - // the parser will already have complained about the keyword being used - return PathResult::NonModule(PartialRes::new(Res::Err)); + (format!("maybe a missing crate `{}`?", ident), None) } } else if i == 0 { (format!("use of undeclared type or module `{}`", ident), None) diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs index d4835c092248e..4bd8efeaa3b97 100644 --- a/src/test/rustdoc-ui/issue-61732.rs +++ b/src/test/rustdoc-ui/issue-61732.rs @@ -1,4 +1,4 @@ // This previously triggered an ICE. pub(in crate::r#mod) fn main() {} -//~^ ERROR expected module, found unresolved item +//~^ ERROR failed to resolve: maybe a missing crate `r#mod` diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr index 6c8ba48864df0..8213422491120 100644 --- a/src/test/rustdoc-ui/issue-61732.stderr +++ b/src/test/rustdoc-ui/issue-61732.stderr @@ -1,11 +1,11 @@ -error[E0577]: expected module, found unresolved item `crate::r#mod` - --> $DIR/issue-61732.rs:3:8 +error[E0433]: failed to resolve: maybe a missing crate `r#mod`? + --> $DIR/issue-61732.rs:3:15 | LL | pub(in crate::r#mod) fn main() {} - | ^^^^^^^^^^^^ not a module + | ^^^^^ maybe a missing crate `r#mod`? error: Compilation failed, aborting rustdoc error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0577`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs index b07de3e341c41..a46ce67d40d5a 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs @@ -1,3 +1,4 @@ use extern::foo; //~ ERROR expected identifier, found keyword `extern` + //~| ERROR unresolved import `r#extern` fn main() {} diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr index 05802f2d36710..edbb36452b6ce 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -9,5 +9,12 @@ help: you can escape reserved keywords to use them as identifiers LL | use r#extern::foo; | ^^^^^^^^ -error: aborting due to previous error +error[E0432]: unresolved import `r#extern` + --> $DIR/keyword-extern-as-identifier-use.rs:1:5 + | +LL | use extern::foo; + | ^^^^^^ maybe a missing crate `r#extern`? + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/resolve/raw-ident-in-path.rs b/src/test/ui/resolve/raw-ident-in-path.rs new file mode 100644 index 0000000000000..1bcbef5943741 --- /dev/null +++ b/src/test/ui/resolve/raw-ident-in-path.rs @@ -0,0 +1,5 @@ +// Regression test for issue #63882. + +type A = crate::r#break; //~ ERROR cannot find type `r#break` in module `crate` + +fn main() {} diff --git a/src/test/ui/resolve/raw-ident-in-path.stderr b/src/test/ui/resolve/raw-ident-in-path.stderr new file mode 100644 index 0000000000000..f2efcbc8e8586 --- /dev/null +++ b/src/test/ui/resolve/raw-ident-in-path.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `r#break` in module `crate` + --> $DIR/raw-ident-in-path.rs:3:17 + | +LL | type A = crate::r#break; + | ^^^^^^^ not found in `crate` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From 81099c27ddc856238d7b1b15c20d487130ef3057 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 10 Mar 2020 10:10:10 +0100 Subject: [PATCH 10/12] VariantSizeDifferences: bail on SizeOverflow --- src/librustc_lint/types.rs | 6 ++---- .../ui/lint/issue-69485-var-size-diffs-too-large.rs | 10 ++++++++++ .../lint/issue-69485-var-size-diffs-too-large.stderr | 8 ++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs create mode 100644 src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 86d93612e993b..2896682ea8268 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -998,10 +998,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let ty = cx.tcx.erase_regions(&t); let layout = match cx.layout_of(ty) { Ok(layout) => layout, - Err(ty::layout::LayoutError::Unknown(_)) => return, - Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => { - bug!("failed to get layout for `{}`: {}", t, err); - } + Err(ty::layout::LayoutError::Unknown(_)) + | Err(ty::layout::LayoutError::SizeOverflow(_)) => return, }; let (variants, tag) = match layout.variants { layout::Variants::Multiple { diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs new file mode 100644 index 0000000000000..49d489d916837 --- /dev/null +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs @@ -0,0 +1,10 @@ +// build-fail +// only-x86_64 + +fn main() { + Bug::V([0; !0]); //~ ERROR is too big for the current +} + +enum Bug { + V([u8; !0]), +} diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr new file mode 100644 index 0000000000000..d31ce9cfe0c2b --- /dev/null +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr @@ -0,0 +1,8 @@ +error: the type `[u8; 18446744073709551615]` is too big for the current architecture + --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12 + | +LL | Bug::V([0; !0]); + | ^^^^^^^ + +error: aborting due to previous error + From ce5e49f86fc8bff241695f8a62e77f517749bd6d Mon Sep 17 00:00:00 2001 From: lzutao Date: Mon, 16 Mar 2020 23:43:42 +0700 Subject: [PATCH 11/12] Use sublice patterns to avoid computing the len --- src/libstd/sys_common/wtf8.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 7509e1ee35dee..77977e255172a 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -599,24 +599,16 @@ impl Wtf8 { #[inline] fn final_lead_surrogate(&self) -> Option { - let len = self.len(); - if len < 3 { - return None; - } - match self.bytes[(len - 3)..] { - [0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes { + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(*b2, *b3)), _ => None, } } #[inline] fn initial_trail_surrogate(&self) -> Option { - let len = self.len(); - if len < 3 { - return None; - } - match self.bytes[..3] { - [0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes { + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(*b2, *b3)), _ => None, } } From e1bc9af9eb503e7ca0027b4d7086c35cd661140e Mon Sep 17 00:00:00 2001 From: lzutao Date: Mon, 16 Mar 2020 23:54:32 +0700 Subject: [PATCH 12/12] Fix wrong deref --- src/libstd/sys_common/wtf8.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 77977e255172a..498950e682101 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -600,7 +600,7 @@ impl Wtf8 { #[inline] fn final_lead_surrogate(&self) -> Option { match self.bytes { - [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(*b2, *b3)), + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), _ => None, } } @@ -608,7 +608,7 @@ impl Wtf8 { #[inline] fn initial_trail_surrogate(&self) -> Option { match self.bytes { - [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(*b2, *b3)), + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)), _ => None, } }