diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 6b6032516ca73..e665e058e6022 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1874,15 +1874,16 @@ impl<'a> LoweringContext<'a> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { // Do not suggest going from `Trait()` to `Trait<>` if data.inputs.len() > 0 { - let split = snippet.find('(').unwrap(); - let trait_name = &snippet[0..split]; - let args = &snippet[split + 1 .. snippet.len() - 1]; - err.span_suggestion( - data.span, - "use angle brackets instead", - format!("{}<{}>", trait_name, args), - Applicability::MaybeIncorrect, - ); + if let Some(split) = snippet.find('(') { + let trait_name = &snippet[0..split]; + let args = &snippet[split + 1 .. snippet.len() - 1]; + err.span_suggestion( + data.span, + "use angle brackets instead", + format!("{}<{}>", trait_name, args), + Applicability::MaybeIncorrect, + ); + } } }; err.emit(); diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 9b7bccca2ddf3..3e71b871801d1 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -164,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.hir.tcx().features().exhaustive_patterns && !v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty() } - }); + }) && (adt_def.did.is_local() || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index); candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns)); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index e7095101f465d..272369008370a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -22,7 +22,7 @@ use rustc::ty::subst::InternalSubsts; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; use rustc::ty::layout::{ - LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, + LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size, }; use crate::interpret::{ @@ -34,6 +34,9 @@ use crate::interpret::{ use crate::const_eval::error_to_const_error; use crate::transform::{MirPass, MirSource}; +/// The maximum number of bytes that we'll allocate space for a return value. +const MAX_ALLOC_LIMIT: u64 = 1024; + pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { @@ -434,6 +437,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) -> Option<()> { let span = source_info.span; + // #66397: Don't try to eval into large places as that can cause an OOM + if place_layout.size >= Size::from_bytes(MAX_ALLOC_LIMIT) { + return None; + } + let overflow_check = self.tcx.sess.overflow_checks(); // Perform any special handling for specific Rvalue types. diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index fde5c5bed4d91..26d37f196befa 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -738,11 +738,7 @@ 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); - Size::ZERO - }, + FieldPlacement::Union(_) => Size::ZERO, FieldPlacement::Array { stride, count } => { let i = i as u64; assert!(i < count); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index aa05a08686a99..e1b540515af41 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1221,16 +1221,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } - /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by - /// removing the dummy `Self` type (`trait_object_dummy_self`). - fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>) - -> ty::ExistentialTraitRef<'tcx> { - if trait_ref.self_ty() != self.tcx().types.trait_object_dummy_self { - bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref); - } - ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) - } - fn conv_object_ty_poly_trait_ref(&self, span: Span, trait_bounds: &[hir::PolyTraitRef], @@ -1412,13 +1402,30 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("regular_traits: {:?}", regular_traits); debug!("auto_traits: {:?}", auto_traits); + // Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by + // removing the dummy `Self` type (`trait_object_dummy_self`). + let trait_ref_to_existential = |trait_ref: ty::TraitRef<'tcx>| { + if trait_ref.self_ty() != dummy_self { + // FIXME: There appears to be a missing filter on top of `expand_trait_aliases`, + // which picks up non-supertraits where clauses - but also, the object safety + // completely ignores trait aliases, which could be object safety hazards. We + // `delay_span_bug` here to avoid an ICE in stable even when the feature is + // disabled. (#66420) + tcx.sess.delay_span_bug(DUMMY_SP, &format!( + "trait_ref_to_existential called on {:?} with non-dummy Self", + trait_ref, + )); + } + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + }; + // Erase the `dummy_self` (`trait_object_dummy_self`) used above. let existential_trait_refs = regular_traits.iter().map(|i| { - i.trait_ref().map_bound(|trait_ref| self.trait_ref_to_existential(trait_ref)) + i.trait_ref().map_bound(|trait_ref| trait_ref_to_existential(trait_ref)) }); let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|b| { - let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); + let trait_ref = trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); ty::ExistentialProjection { ty: b.ty, item_def_id: b.projection_ty.item_def_id, diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index ff9c945eec452..6e37c0dbbdf9d 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -244,7 +244,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { // can be reborrowed without needing to spill to a temporary. // If this were not the case, then we could conceivably have // to create intermediate temporaries.) - let ty = self.fcx.tables.borrow().expr_ty(expr); - self.record(ty, scope, Some(expr), expr.span); + // + // The type table might not have information for this expression + // if it is in a malformed scope. (#66387) + if let Some(ty) = self.fcx.tables.borrow().expr_ty_opt(expr) { + self.record(ty, scope, Some(expr), expr.span); + } else { + self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node"); + } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f7132cd868aac..a02d5b5a571c5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3010,7 +3010,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: bool, mutate_fullfillment_errors: impl Fn(&mut Vec>), ) { - if let Err(mut errors) = self.fulfillment_cx.borrow_mut().select_where_possible(self) { + let result = self.fulfillment_cx.borrow_mut().select_where_possible(self); + if let Err(mut errors) = result { mutate_fullfillment_errors(&mut errors); self.report_fulfillment_errors(&errors, self.inh.body_id, fallback_has_occurred); } diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 84c86c9651fcf..5217f63660795 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -655,7 +655,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, break } - let meta = attr.meta().unwrap(); + let meta = match attr.meta() { + Some(meta) => meta, + None => continue, + }; depr = match &meta.kind { MetaItemKind::Word => Some(Deprecation { since: None, note: None }), MetaItemKind::NameValue(..) => { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e81d4573b73e5..e6e9d37962af4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -442,7 +442,9 @@ impl<'a> Parser<'a> { crate fn unexpected(&mut self) -> PResult<'a, T> { match self.expect_one_of(&[], &[]) { Err(e) => Err(e), - Ok(_) => unreachable!(), + // We can get `Ok(true)` from `recover_closing_delimiter` + // which is called in `expected_one_of_not_found`. + Ok(_) => FatalError.raise(), } } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 37310f46f7eed..3c7f80aa399bf 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -374,10 +374,12 @@ impl<'a, 'b> Context<'a, 'b> { format!("are {} arguments", count) }, )); - e.span_label( - self.args[pos].span, - "this parameter corresponds to the precision flag", - ); + if let Some(arg) = self.args.get(pos) { + e.span_label( + arg.span, + "this parameter corresponds to the precision flag", + ); + } zero_based_note = true; } _ => {} diff --git a/src/test/ui/async-await/issue-66387-if-without-else.rs b/src/test/ui/async-await/issue-66387-if-without-else.rs new file mode 100644 index 0000000000000..aa5a8db61210d --- /dev/null +++ b/src/test/ui/async-await/issue-66387-if-without-else.rs @@ -0,0 +1,10 @@ +// edition:2018 +async fn f() -> i32 { + if true { //~ ERROR if may be missing an else clause + return 0; + } + // An `if` block without `else` causes the type table not to have a type for this expr. + // Check that we do not unconditionally access the type table and we don't ICE. +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-66387-if-without-else.stderr b/src/test/ui/async-await/issue-66387-if-without-else.stderr new file mode 100644 index 0000000000000..32952059525a0 --- /dev/null +++ b/src/test/ui/async-await/issue-66387-if-without-else.stderr @@ -0,0 +1,16 @@ +error[E0317]: if may be missing an else clause + --> $DIR/issue-66387-if-without-else.rs:3:5 + | +LL | / if true { +LL | | return 0; +LL | | } + | |_____^ expected (), found i32 + | + = note: expected type `()` + found type `i32` + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0317`. diff --git a/src/test/ui/consts/issue-66342.rs b/src/test/ui/consts/issue-66342.rs new file mode 100644 index 0000000000000..417f69041658d --- /dev/null +++ b/src/test/ui/consts/issue-66342.rs @@ -0,0 +1,12 @@ +// check-pass +// only-x86_64 + +// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash. + +fn foo() -> [u8; 4 * 1024 * 1024 * 1024 * 1024] { + unimplemented!() +} + +fn main() { + foo(); +} diff --git a/src/test/ui/consts/issue-66397.rs b/src/test/ui/consts/issue-66397.rs new file mode 100644 index 0000000000000..1b4aff43b5bf1 --- /dev/null +++ b/src/test/ui/consts/issue-66397.rs @@ -0,0 +1,8 @@ +// check-pass +// only-x86_64 + +// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash. + +fn main() { + [0; 4 * 1024 * 1024 * 1024 * 1024]; +} diff --git a/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs new file mode 100644 index 0000000000000..c0cde75d4caeb --- /dev/null +++ b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -0,0 +1,11 @@ +// The original problem in #66340 was that `find_deprecation_generic` +// called `attr.meta().unwrap()` under the assumption that the attribute +// was a well-formed `MetaItem`. + +fn main() { + foo() +} + +#[deprecated(note = test)] +//~^ ERROR expected unsuffixed literal or identifier, found `test` +fn foo() {} diff --git a/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr new file mode 100644 index 0000000000000..24178faf8de78 --- /dev/null +++ b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -0,0 +1,8 @@ +error: expected unsuffixed literal or identifier, found `test` + --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 + | +LL | #[deprecated(note = test)] + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/if/ifmt-bad-arg.rs b/src/test/ui/if/ifmt-bad-arg.rs index ba897f171af25..a0b0a8fb98594 100644 --- a/src/test/ui/if/ifmt-bad-arg.rs +++ b/src/test/ui/if/ifmt-bad-arg.rs @@ -86,4 +86,9 @@ tenth number: {}", println!("{:foo}", 1); //~ ERROR unknown format trait `foo` println!("{5} {:4$} {6:7$}", 1); //~^ ERROR invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument) + + // We used to ICE here because we tried to unconditionally access the first argument, which + // doesn't exist. + println!("{:.*}"); + //~^ ERROR 2 positional arguments in format string, but no arguments were given } diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index c58cbc312335a..11dcc3a6d232e 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -285,6 +285,17 @@ LL | println!("{5} {:4$} {6:7$}", 1); = note: positional arguments are zero-based = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html +error: 2 positional arguments in format string, but no arguments were given + --> $DIR/ifmt-bad-arg.rs:92:15 + | +LL | println!("{:.*}"); + | ^^--^ + | | + | this precision flag adds an extra required argument at position 0, which is why there are 2 arguments expected + | + = note: positional arguments are zero-based + = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html + error[E0308]: mismatched types --> $DIR/ifmt-bad-arg.rs:78:32 | @@ -303,6 +314,6 @@ LL | println!("{} {:07$.*} {}", 1, 3.2, 4); = note: expected type `&usize` found type `&{float}` -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-65462.rs b/src/test/ui/issues/issue-65462.rs new file mode 100644 index 0000000000000..8c39ea531d244 --- /dev/null +++ b/src/test/ui/issues/issue-65462.rs @@ -0,0 +1,15 @@ +// build-pass + +enum Empty {} +enum Enum { + Empty( Empty ) +} + +fn foobar() -> Option< Enum > { + let value: Option< Empty > = None; + Some( Enum::Empty( value? ) ) +} + +fn main() { + foobar(); +} diff --git a/src/test/ui/issues/issue-65673.rs b/src/test/ui/issues/issue-65673.rs new file mode 100644 index 0000000000000..4b47bd493a568 --- /dev/null +++ b/src/test/ui/issues/issue-65673.rs @@ -0,0 +1,12 @@ +#![feature(trait_alias)] // Enabled to reduce stderr output, but can be triggered even if disabled. +trait Trait {} +trait WithType { + type Ctx; +} +trait Alias = where T: Trait; + +impl WithType for T { + type Ctx = dyn Alias; +//~^ ERROR the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time +} +fn main() {} diff --git a/src/test/ui/issues/issue-65673.stderr b/src/test/ui/issues/issue-65673.stderr new file mode 100644 index 0000000000000..a556e35b6a944 --- /dev/null +++ b/src/test/ui/issues/issue-65673.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/issue-65673.rs:9:5 + | +LL | type Ctx; + | --- associated type defined here +... +LL | impl WithType for T { + | ---------------------- in this `impl` item +LL | type Ctx = dyn Alias; + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)` + = note: to learn more, visit + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-66353.rs b/src/test/ui/issues/issue-66353.rs new file mode 100644 index 0000000000000..d8abdd5206ef4 --- /dev/null +++ b/src/test/ui/issues/issue-66353.rs @@ -0,0 +1,15 @@ +// #66353: ICE when trying to recover from incorrect associated type + +trait _Func { + fn func(_: Self); +} + +trait _A { + type AssocT; +} + +fn main() { + _Func::< <() as _A>::AssocT >::func(()); + //~^ ERROR the trait bound `(): _A` is not satisfied + //~| ERROR the trait bound `(): _Func<_>` is not satisfied +} diff --git a/src/test/ui/issues/issue-66353.stderr b/src/test/ui/issues/issue-66353.stderr new file mode 100644 index 0000000000000..8fd50300ca63e --- /dev/null +++ b/src/test/ui/issues/issue-66353.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `(): _A` is not satisfied + --> $DIR/issue-66353.rs:12:14 + | +LL | _Func::< <() as _A>::AssocT >::func(()); + | ^^^^^^^^^^^^^^^^^^ the trait `_A` is not implemented for `()` + +error[E0277]: the trait bound `(): _Func<_>` is not satisfied + --> $DIR/issue-66353.rs:12:41 + | +LL | fn func(_: Self); + | ----------------- required by `_Func::func` +... +LL | _Func::< <() as _A>::AssocT >::func(()); + | ^^ the trait `_Func<_>` is not implemented for `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.rs b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs new file mode 100644 index 0000000000000..1730adfa91419 --- /dev/null +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.rs @@ -0,0 +1,14 @@ +// The problem in #66357 was that the call trace: +// +// - parse_fn_block_decl +// - expect_or +// - unexpected +// - expect_one_of +// - expected_one_of_not_found +// - recover_closing_delimiter +// +// ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`. + +fn f() { |[](* } +//~^ ERROR expected one of `,` or `:`, found `(` +//~| ERROR expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` diff --git a/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr new file mode 100644 index 0000000000000..c7b6e15ddace8 --- /dev/null +++ b/src/test/ui/parser/issue-66357-unexpected-unreachable.stderr @@ -0,0 +1,16 @@ +error: expected one of `,` or `:`, found `(` + --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 + | +LL | fn f() { |[](* } + | ^ expected one of `,` or `:` here + +error: expected one of `)`, `-`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*` + --> $DIR/issue-66357-unexpected-unreachable.rs:12:14 + | +LL | fn f() { |[](* } + | -^ help: `)` may belong here + | | + | unclosed delimiter + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs new file mode 100644 index 0000000000000..5f86db86d4477 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs @@ -0,0 +1,8 @@ +#[non_exhaustive] +pub enum NonExhaustiveMonovariant { + Variant(u32), +} + +pub enum ExhaustiveMonovariant { + Variant(u32), +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs new file mode 100644 index 0000000000000..be775b37f7b77 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs @@ -0,0 +1,42 @@ +// Test that the borrow checker doesn't consider checking an exhaustive pattern +// as an access. + +// check-pass + +// aux-build:monovariants.rs +extern crate monovariants; + +use monovariants::ExhaustiveMonovariant; + +enum Local { + Variant(u32), +} + +#[non_exhaustive] +enum LocalNonExhaustive { + Variant(u32), +} + +fn main() { + let mut x = ExhaustiveMonovariant::Variant(1); + let y = &mut x; + match x { + ExhaustiveMonovariant::Variant(_) => {}, + _ => {}, + } + drop(y); + let mut x = Local::Variant(1); + let y = &mut x; + match x { + Local::Variant(_) => {}, + _ => {}, + } + drop(y); + let mut x = LocalNonExhaustive::Variant(1); + let y = &mut x; + match x { + LocalNonExhaustive::Variant(_) => {}, + _ => {}, + } + drop(y); +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs new file mode 100644 index 0000000000000..00dcf89c7aa67 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs @@ -0,0 +1,18 @@ +// Test that the borrow checker considers `#[non_exhaustive]` when checking +// whether a match contains a discriminant read. + +// aux-build:monovariants.rs +extern crate monovariants; + +use monovariants::NonExhaustiveMonovariant; + +fn main() { + let mut x = NonExhaustiveMonovariant::Variant(1); + let y = &mut x; + match x { + NonExhaustiveMonovariant::Variant(_) => {}, + //~^ ERROR cannot use `x` because it was mutably borrowed + _ => {}, + } + drop(y); +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr new file mode 100644 index 0000000000000..9edfa84cbc085 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr @@ -0,0 +1,15 @@ +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-non-exhaustive.rs:13:9 + | +LL | let y = &mut x; + | ------ borrow of `x` occurs here +LL | match x { +LL | NonExhaustiveMonovariant::Variant(_) => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of borrowed `x` +... +LL | drop(y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0503`.