diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ead39d702635a..3046fd5e680c8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1430,10 +1430,8 @@ impl Expr<'_> { matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static, _) | Res::Err) } - // Type ascription inherits its place expression kind from its - // operand. See: - // https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries - ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from), + // We always treat type ascriptions as rvalues + ExprKind::Type(_, _) => false, ExprKind::Unary(UnOp::UnDeref, _) => true, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 09d5b10210312..34f39a19d4f87 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -792,6 +792,13 @@ impl<'hir> Map<'hir> { } } + pub fn maybe_expr(&self, id: HirId) -> Option<&'hir Expr<'hir>> { + match self.find(id) { + Some(Node::Expr(expr)) => Some(expr), + _ => None, + } + } + pub fn opt_name(&self, id: HirId) -> Option { Some(match self.get(id) { Node::Item(i) => i.ident.name, diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 00db19019c480..b5d8df18bf517 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -18,7 +18,7 @@ use rustc_target::abi::VariantIdx; )] pub enum PlaceBase { /// A temporary variable. - Rvalue, + Rvalue(HirId), /// A named `static` item. StaticItem, /// A named local variable. diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index cf2e4e8916d0a..4220cdd2ca07f 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -6,8 +6,8 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::thir::*; use rustc_hir::def_id::DefId; use rustc_hir::HirId; -use rustc_middle::middle::region; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; +use rustc_middle::middle::region; use rustc_middle::mir::AssertKind::BoundsCheck; use rustc_middle::mir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; @@ -57,7 +57,8 @@ crate enum PlaceBase { /// DefId of the closure closure_def_id: DefId, /// The trait closure implements, `Fn`, `FnMut`, `FnOnce` - closure_kind: ty::ClosureKind }, + closure_kind: ty::ClosureKind, + }, } /// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a @@ -81,8 +82,7 @@ crate struct PlaceBuilder<'tcx> { fn convert_to_hir_projections_and_truncate_for_capture<'tcx>( mir_projections: &[PlaceElem<'tcx>], ) -> Vec { - - let mut hir_projections = Vec::new(); + let mut hir_projections = Vec::new(); for mir_projection in mir_projections { let hir_projection = match mir_projection { @@ -91,20 +91,20 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>( // We will never encouter this for multivariant enums, // read the comment for `Downcast`. HirProjectionKind::Field(field.index() as u32, VariantIdx::new(0)) - }, + } ProjectionElem::Downcast(..) => { // This projections exist only for enums that have // multiple variants. Since such enums that are captured // completely, we can stop here. - break - }, + break; + } ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { // We don't capture array-access projections. // We can stop here as arrays are captured completely. - break - }, + break; + } }; hir_projections.push(hir_projection); @@ -181,9 +181,9 @@ fn find_capture_matching_projections<'a, 'tcx>( // If an ancestor is found, `idx` is the index within the list of captured places // for root variable `var_hir_id` and `capture` is the `ty::CapturedPlace` itself. let (idx, capture) = root_variable_min_captures.iter().enumerate().find(|(_, capture)| { - let possible_ancestor_proj_kinds = - capture.place.projections.iter().map(|proj| proj.kind).collect(); - is_ancestor_or_same_capture(&possible_ancestor_proj_kinds, &hir_projections) + let possible_ancestor_proj_kinds = + capture.place.projections.iter().map(|proj| proj.kind).collect(); + is_ancestor_or_same_capture(&possible_ancestor_proj_kinds, &hir_projections) })?; // Convert index to be from the presepective of the entire closure_min_captures map @@ -213,35 +213,34 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( ty::ClosureKind::FnOnce => {} } - let (capture_index, capture) = - if let Some(capture_details) = find_capture_matching_projections( + let (capture_index, capture) = if let Some(capture_details) = + find_capture_matching_projections( typeck_results, var_hir_id, closure_def_id, &from_builder.projection, ) { - capture_details - } else { - if !tcx.features().capture_disjoint_fields { - bug!( - "No associated capture found for {:?}[{:#?}] even though \ + capture_details + } else { + if !tcx.features().capture_disjoint_fields { + bug!( + "No associated capture found for {:?}[{:#?}] even though \ capture_disjoint_fields isn't enabled", - var_hir_id, - from_builder.projection - ) - } else { - // FIXME(project-rfc-2229#24): Handle this case properly - debug!( - "No associated capture found for {:?}[{:#?}]", - var_hir_id, - from_builder.projection, - ); - } - return Err(var_hir_id); - }; + var_hir_id, + from_builder.projection + ) + } else { + // FIXME(project-rfc-2229#24): Handle this case properly + debug!( + "No associated capture found for {:?}[{:#?}]", + var_hir_id, from_builder.projection, + ); + } + return Err(var_hir_id); + }; - let closure_ty = - typeck_results.node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); + let closure_ty = typeck_results + .node_type(tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local())); let substs = match closure_ty.kind() { ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), @@ -256,7 +255,8 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( // we know that the capture exists and is the `capture_index`-th capture. let var_ty = substs.tupled_upvars_ty().tuple_element_ty(capture_index).unwrap(); - upvar_resolved_place_builder = upvar_resolved_place_builder.field(Field::new(capture_index), var_ty); + upvar_resolved_place_builder = + upvar_resolved_place_builder.field(Field::new(capture_index), var_ty); // If the variable is captured via ByRef(Immutable/Mutable) Borrow, // we need to deref it @@ -270,8 +270,9 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( // We used some of the projections to build the capture itself, // now we apply the remaining to the upvar resolved place. - upvar_resolved_place_builder.projection.extend( - curr_projections.drain(next_projection..)); + upvar_resolved_place_builder + .projection + .extend(curr_projections.drain(next_projection..)); Ok(upvar_resolved_place_builder) } @@ -356,7 +357,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// This is used when constructing a compound `Place`, so that we can avoid creating /// intermediate `Place` values until we know the full set of projections. - crate fn as_place_builder(&mut self, block: BasicBlock, expr: M) -> BlockAnd> + crate fn as_place_builder( + &mut self, + block: BasicBlock, + expr: M, + ) -> BlockAnd> where M: Mirror<'tcx, Output = Expr<'tcx>>, { @@ -456,38 +461,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(place_builder) } - ExprKind::PlaceTypeAscription { source, user_ty } => { - let source = this.hir.mirror(source); - let place_builder = unpack!( - block = this.expr_as_place(block, source, mutability, fake_borrow_temps,) - ); - if let Some(user_ty) = user_ty { - let annotation_index = - this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { - span: source_info.span, - user_ty, - inferred_ty: expr.ty, - }); - - let place = - place_builder.clone().into_place(this.hir.tcx(), this.hir.typeck_results()); - this.cfg.push( - block, - Statement { - source_info, - kind: StatementKind::AscribeUserType( - box ( - place, - UserTypeProjection { base: annotation_index, projs: vec![] }, - ), - Variance::Invariant, - ), - }, - ); - } - block.and(place_builder) - } - ExprKind::ValueTypeAscription { source, user_ty } => { + ExprKind::TypeAscription { source, user_ty } => { let source = this.hir.mirror(source); let temp = unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability)); @@ -626,7 +600,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if is_outermost_index { self.read_fake_borrows(block, fake_borrow_temps, source_info) } else { - base_place = base_place.expect_upvars_resolved(self.hir.tcx(), self.hir.typeck_results()); + base_place = + base_place.expect_upvars_resolved(self.hir.tcx(), self.hir.typeck_results()); self.add_fake_borrows_of_base( &base_place, block, @@ -678,7 +653,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); let local = match base_place.base { PlaceBase::Local(local) => local, - PlaceBase::Upvar { .. } => bug!("Expected PlacseBase::Local found Upvar") + PlaceBase::Upvar { .. } => bug!("Expected PlacseBase::Local found Upvar"), }; let place_ty = Place::ty_from(local, &base_place.projection, &self.local_decls, tcx); diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3f381f3f15e8e..1a7a8bb89a02d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -2,9 +2,9 @@ use rustc_index::vec::Idx; +use crate::build::expr::as_place::PlaceBase; use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; -use crate::build::expr::as_place::PlaceBase; use crate::thir::*; use rustc_middle::middle::region; use rustc_middle::mir::AssertKind; @@ -269,11 +269,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Return { .. } | ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } - | ExprKind::PlaceTypeAscription { .. } - | ExprKind::ValueTypeAscription { .. } => { + | ExprKind::TypeAscription { .. } => { // these do not have corresponding `Rvalue` variants, // so make an operand and then return that - debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Rvalue(RvalueFunc::AsRvalue)))); + debug_assert!(!matches!( + Category::of(&expr.kind), + Some(Category::Rvalue(RvalueFunc::AsRvalue)) + )); let operand = unpack!(block = this.as_operand(block, scope, expr)); block.and(Rvalue::Use(operand)) } @@ -400,34 +402,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We are capturing a path that starts off a local variable in the parent. // The mutability of the current capture is same as the mutability // of the local declaration in the parent. - PlaceBase::Local(local) => this.local_decls[local].mutability, + PlaceBase::Local(local) => this.local_decls[local].mutability, // Parent is a closure and we are capturing a path that is captured // by the parent itself. The mutability of the current capture // is same as that of the capture in the parent closure. PlaceBase::Upvar { .. } => { - let enclosing_upvars_resolved = arg_place_builder.clone().into_place( - this.hir.tcx(), - this.hir.typeck_results()); + let enclosing_upvars_resolved = + arg_place_builder.clone().into_place(this.hir.tcx(), this.hir.typeck_results()); match enclosing_upvars_resolved.as_ref() { - PlaceRef { local, projection: &[ProjectionElem::Field(upvar_index, _), ..] } + PlaceRef { + local, + projection: &[ProjectionElem::Field(upvar_index, _), ..], + } | PlaceRef { local, - projection: &[ProjectionElem::Deref, ProjectionElem::Field(upvar_index, _), ..] } => { - // Not in a closure - debug_assert!( - local == Local::new(1), - "Expected local to be Local(1), found {:?}", - local - ); - // Not in a closure - debug_assert!( - this.upvar_mutbls.len() > upvar_index.index(), - "Unexpected capture place, upvar_mutbls={:#?}, upvar_index={:?}", - this.upvar_mutbls, upvar_index - ); - this.upvar_mutbls[upvar_index.index()] - } + projection: + &[ProjectionElem::Deref, ProjectionElem::Field(upvar_index, _), ..], + } => { + // Not in a closure + debug_assert!( + local == Local::new(1), + "Expected local to be Local(1), found {:?}", + local + ); + // Not in a closure + debug_assert!( + this.upvar_mutbls.len() > upvar_index.index(), + "Unexpected capture place, upvar_mutbls={:#?}, upvar_index={:?}", + this.upvar_mutbls, + upvar_index + ); + this.upvar_mutbls[upvar_index.index()] + } _ => bug!("Unexpected capture place"), } } @@ -438,9 +445,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, }; - let arg_place = arg_place_builder.into_place( - this.hir.tcx(), - this.hir.typeck_results()); + let arg_place = arg_place_builder.into_place(this.hir.tcx(), this.hir.typeck_results()); this.cfg.push_assign( block, diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index 8561170856fd4..03527e21f0abe 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -40,8 +40,7 @@ impl Category { | ExprKind::Index { .. } | ExprKind::UpvarRef { .. } | ExprKind::VarRef { .. } - | ExprKind::PlaceTypeAscription { .. } - | ExprKind::ValueTypeAscription { .. } => Some(Category::Place), + | ExprKind::TypeAscription { .. } => Some(Category::Place), ExprKind::LogicalOp { .. } | ExprKind::Match { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 09281799041ee..a5efeb03ea9ea 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -40,7 +40,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; let source_info = this.source_info(expr_span); - let expr_is_block_or_scope = matches!(expr.kind, ExprKind::Block { .. } | ExprKind::Scope { .. }); + let expr_is_block_or_scope = + matches!(expr.kind, ExprKind::Block { .. } | ExprKind::Scope { .. }); let schedule_drop = move |this: &mut Self| { if let Some(drop_scope) = scope { @@ -71,11 +72,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::NeverToAny { source } => { let source = this.hir.mirror(source); - let is_call = matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. }); + let is_call = + matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. }); // (#66975) Source could be a const of type `!`, so has to // exist in the generated MIR. - unpack!(block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,)); + unpack!( + block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,) + ); // This is an optimization. If the expression was a call then we already have an // unreachable block. Don't bother to terminate it and create a new one. @@ -433,8 +437,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Avoid creating a temporary ExprKind::VarRef { .. } | ExprKind::UpvarRef { .. } - | ExprKind::PlaceTypeAscription { .. } - | ExprKind::ValueTypeAscription { .. } => { + | ExprKind::TypeAscription { .. } => { debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); let place = unpack!(block = this.as_place(block, expr)); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 417f9bded0988..e81acb012b86b 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -648,10 +648,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( let cast_expr = Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast }; debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty); - ExprKind::ValueTypeAscription { - source: cast_expr.to_ref(), - user_ty: Some(*user_ty), - } + ExprKind::TypeAscription { source: cast_expr.to_ref(), user_ty: Some(*user_ty) } } else { cast } @@ -660,11 +657,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( let user_provided_types = cx.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(ty.hir_id).copied(); debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); - if source.is_syntactic_place_expr() { - ExprKind::PlaceTypeAscription { source: source.to_ref(), user_ty } - } else { - ExprKind::ValueTypeAscription { source: source.to_ref(), user_ty } - } + ExprKind::TypeAscription { source: source.to_ref(), user_ty } } hir::ExprKind::DropTemps(ref source) => ExprKind::Use { source: source.to_ref() }, hir::ExprKind::Box(ref value) => ExprKind::Box { value: value.to_ref() }, diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index ace9cad4d2996..dc6ac87a05a84 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -263,12 +263,7 @@ crate enum ExprKind<'tcx> { fields: Vec>, base: Option>, }, - PlaceTypeAscription { - source: ExprRef<'tcx>, - /// Type that the user gave to this expression - user_ty: Option>>, - }, - ValueTypeAscription { + TypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression user_ty: Option>>, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d76a80d5a3990..ecdeff62a65c0 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -48,11 +48,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode}; use std::fmt::Display; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - fn check_expr_eq_type(&self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>) { - let ty = self.check_expr_with_hint(expr, expected); - self.demand_eqtype(expr.span, expected, ty); - } - pub fn check_expr_has_type_or_error( &self, expr: &'tcx hir::Expr<'tcx>, @@ -282,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Cast(ref e, ref t) => self.check_expr_cast(e, t, expr), ExprKind::Type(ref e, ref t) => { let ty = self.to_ty_saving_user_provided_ty(&t); - self.check_expr_eq_type(&e, ty); + self.check_expr_coercable_to_type(e, ty, None); ty } ExprKind::DropTemps(ref e) => self.check_expr_with_expectation(e, expected), diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 8177b363a5a5b..3a2401195a5b9 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -85,6 +85,7 @@ mod op; mod pat; mod place_op; mod regionck; +mod type_ascription; mod upvar; mod wfcheck; pub mod writeback; @@ -611,6 +612,8 @@ fn typeck_with_fallback<'tcx>( // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. fcx.check_casts(); + fcx.analyze_type_ascriptions(body); + // Closure and generator analysis may run after fallback // because they don't constrain other type variables. fcx.closure_analyze(body); diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index 88e8dd3cb129a..cefd41082e3e5 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -484,7 +484,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { place_with_id: &PlaceWithHirId<'tcx>, span: Span, ) { - if let PlaceBase::Rvalue = place_with_id.place.base { + if let PlaceBase::Rvalue(_) = place_with_id.place.base { if place_with_id.place.projections.is_empty() { let typ = self.resolve_type(place_with_id.place.ty()); let body_id = self.body_id; diff --git a/compiler/rustc_typeck/src/check/type_ascription.rs b/compiler/rustc_typeck/src/check/type_ascription.rs new file mode 100644 index 0000000000000..2a0373e5d47a3 --- /dev/null +++ b/compiler/rustc_typeck/src/check/type_ascription.rs @@ -0,0 +1,191 @@ +use super::FnCtxt; +use crate::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_hir::hir_id::HirId; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; +use rustc_middle::ty; +use rustc_span::hygiene::SyntaxContext; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +// Checks for type ascriptions in lvalue contexts, i.e. in situations such as +// (x : T) = ..., &(x : T), &mut (x : T) and (x : T).foo(...), where +// type ascriptions can potentially lead to type unsoundness problems +struct TypeAscriptionValidator<'a, 'tcx> { + fcx: &'a FnCtxt<'a, 'tcx>, + finder: TypeAscriptionFinder<'a>, +} + +impl<'a, 'tcx> Delegate<'tcx> for TypeAscriptionValidator<'a, 'tcx> { + fn consume( + &mut self, + _place_with_id: &PlaceWithHirId<'tcx>, + _diag_expr_id: hir::HirId, + _mode: ConsumeMode, + ) { + } + + fn borrow( + &mut self, + place_with_id: &PlaceWithHirId<'tcx>, + _diag_expr_id: hir::HirId, + bk: ty::BorrowKind, + ) { + debug!( + "TypeAscriptionkind::borrow(place: {:?}, borrow_kind: {:?})", + place_with_id.place, bk + ); + + if let PlaceBase::Rvalue(id) = place_with_id.place.base { + if let Some(expr) = self.fcx.tcx.hir().maybe_expr(id) { + debug!("expr behind place: {:?}", expr); + self.finder.visit_expr(expr); + if let Some(ascr_expr) = self.finder.found_type_ascr() { + if let hir::ExprKind::Type(ref e, ref t) = ascr_expr.kind { + let span = ascr_expr.span; + let mut err = self.fcx.tcx.sess.struct_span_err( + span, + "type ascriptions are not allowed in lvalue contexts", + ); + + if let Some((span, ident)) = self.maybe_get_span_ident_for_diagnostics(e) { + if let Ok(ty_str) = + self.fcx.tcx.sess.source_map().span_to_snippet(t.span) + { + err.span_suggestion( + span, + "try to use the type ascription when creating the local variable", + format!("let {}: {}", ident, ty_str), + Applicability::MaybeIncorrect, + ); + } + } + err.emit(); + } + } + self.finder.reset(); + } + } + } + + fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) { + debug!( + "TypeAscription::mutate(assignee_place: {:?}, diag_expr_id: {:?})", + assignee_place, diag_expr_id + ); + + if let PlaceBase::Rvalue(id) = assignee_place.place.base { + if let Some(expr) = self.fcx.tcx.hir().maybe_expr(id) { + debug!("expr behind place: {:?}", expr); + if let hir::ExprKind::Type(_, _) = expr.kind { + let span = expr.span; + let mut err = self.fcx.tcx.sess.struct_span_err( + span, + "type ascriptions are not allowed in lvalue contexts", + ); + err.emit(); + } + } + } + } +} + +impl TypeAscriptionValidator<'a, 'tcx> { + // Try to get the necessary information for an error suggestion, in case the + // place on which the type ascription was used is a local variable. + fn maybe_get_span_ident_for_diagnostics(&self, e: &hir::Expr<'_>) -> Option<(Span, Ident)> { + match e.kind { + hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => { + let hir::Path { res, segments, .. } = path; + if let Res::Local(id) = res { + // Span for the definition of the local variable + let span = self.fcx.tcx.hir().span(*id); + let source_map = self.fcx.tcx.sess.source_map(); + + if let Ok(file_lines) = source_map.span_to_lines(span) { + let source_file = file_lines.file; + let lines = file_lines.lines; + + // Only create suggestion if the assignment operator is on the first line + let line_bounds_range = + lines.get(0).and_then(|l| Some(source_file.line_bounds(l.line_index))); + if let Some(range) = line_bounds_range { + let line_span = + Span::new(range.start, range.end, SyntaxContext::root()); + if let Ok(line_string) = source_map.span_to_snippet(line_span) { + if line_string.contains("=") { + let span_til_eq = source_map.span_until_char(line_span, '='); + if segments.len() == 1 { + let ident = segments[0].ident; + return Some((span_til_eq, ident)); + } + } + } + } + } + } + } + _ => {} + } + None + } +} + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub fn analyze_type_ascriptions(&self, body: &'tcx hir::Body<'tcx>) { + let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); + let finder = TypeAscriptionFinder::new(); + let mut delegate = TypeAscriptionValidator { fcx: self, finder }; + ExprUseVisitor::new( + &mut delegate, + &self.infcx, + body_owner_def_id, + self.param_env, + &self.typeck_results.borrow(), + ) + .consume_body(body); + } +} + +struct TypeAscriptionFinder<'tcx> { + found: Option<&'tcx hir::Expr<'tcx>>, + found_ids: Vec, +} + +impl<'tcx> TypeAscriptionFinder<'tcx> { + fn new() -> TypeAscriptionFinder<'tcx> { + TypeAscriptionFinder { found: None, found_ids: vec![] } + } + + fn found_type_ascr(&self) -> Option<&'tcx hir::Expr<'tcx>> { + self.found + } + + fn reset(&mut self) { + self.found = None; + } +} + +impl Visitor<'tcx> for TypeAscriptionFinder<'tcx> { + type Map = intravisit::ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::None + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + match expr.kind { + hir::ExprKind::Type(..) => { + if !self.found_ids.contains(&expr.hir_id) { + self.found = Some(expr); + self.found_ids.push(expr.hir_id); + return; + } + } + _ => intravisit::walk_expr(self, expr), + } + } +} diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 3ce244e11bf45..ba1b6c7990403 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -116,11 +116,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } pub fn consume_body(&mut self, body: &hir::Body<'_>) { - debug!("consume_body(body={:?})", body); + debug!("expr_use_visitor::consume_body(body={:?})", body); for param in body.params { let param_ty = return_if_err!(self.mc.pat_ty_adjusted(¶m.pat)); - debug!("consume_body: param_ty = {:?}", param_ty); + debug!("expr_use_visitor::consume_body: param_ty = {:?}", param_ty); let param_place = self.mc.cat_rvalue(param.hir_id, param.pat.span, param_ty); @@ -135,7 +135,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) { - debug!("delegate_consume(place_with_id={:?})", place_with_id); + debug!("expr_use_visitor::delegate_consume(place_with_id={:?})", place_with_id); let mode = copy_or_move(&self.mc, place_with_id); self.delegate.consume(place_with_id, diag_expr_id, mode); @@ -148,7 +148,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } pub fn consume_expr(&mut self, expr: &hir::Expr<'_>) { - debug!("consume_expr(expr={:?})", expr); + debug!("expr_use_visitor.consume_expr(expr={:?})", expr); let place_with_id = return_if_err!(self.mc.cat_expr(expr)); self.delegate_consume(&place_with_id, place_with_id.hir_id); @@ -156,13 +156,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn mutate_expr(&mut self, expr: &hir::Expr<'_>) { + debug!("mutate_expr(expr: {:?})", expr); let place_with_id = return_if_err!(self.mc.cat_expr(expr)); self.delegate.mutate(&place_with_id, place_with_id.hir_id); self.walk_expr(expr); } fn borrow_expr(&mut self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) { - debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); + debug!("expr_use_visitor::borrow_expr(expr={:?}, bk={:?})", expr, bk); let place_with_id = return_if_err!(self.mc.cat_expr(expr)); self.delegate.borrow(&place_with_id, place_with_id.hir_id, bk); @@ -175,14 +176,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) { - debug!("walk_expr(expr={:?})", expr); + debug!("expr_use_visitor::walk_expr(expr={:?})", expr); self.walk_adjustment(expr); match expr.kind { hir::ExprKind::Path(_) => {} - hir::ExprKind::Type(ref subexpr, _) => self.walk_expr(subexpr), + hir::ExprKind::Type(ref subexpr, _) => { + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + + self.delegate_consume(&place_with_id, place_with_id.hir_id); + self.consume_expr(subexpr); + } hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base) => { // *base @@ -345,6 +351,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) { + debug!("expr_use_visitor::walk_stmt(stmt: {:?})", stmt); match stmt.kind { hir::StmtKind::Local(ref local) => { self.walk_local(&local); @@ -362,6 +369,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn walk_local(&mut self, local: &hir::Local<'_>) { + debug!("expr_use_visitor::walk_local(local: {:?})", local); if let Some(ref expr) = local.init { // Variable declarations with // initializers are considered @@ -446,6 +454,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // consumed or borrowed as part of the automatic adjustment // process. fn walk_adjustment(&mut self, expr: &hir::Expr<'_>) { + debug!("expr_use_visitor::walk_adjustments(expr: {:?})", expr); + let adjustments = self.mc.typeck_results.expr_adjustments(expr); let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { @@ -465,8 +475,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // `x.deref()`. Since `deref()` is declared with `&self`, // this is an autoref of `x`. adjustment::Adjust::Deref(Some(ref deref)) => { + debug!("expr_use_visitor::walk_adjustment: Adjust::Deref({:?})", deref); let bk = ty::BorrowKind::from_mutbl(deref.mutbl); - self.delegate.borrow(&place_with_id, place_with_id.hir_id, bk); + + self.delegate.borrow(&place_with_id, place_with_id.hir_id, bk) } adjustment::Adjust::Borrow(ref autoref) => { @@ -488,22 +500,20 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!( - "walk_autoref(expr.hir_id={} base_place={:?} autoref={:?})", + "expr_use_visitor::walk_autoref(expr.hir_id={} base_place={:?} autoref={:?})", expr.hir_id, base_place, autoref ); match *autoref { adjustment::AutoBorrow::Ref(_, m) => { self.delegate.borrow( - base_place, + &base_place, base_place.hir_id, ty::BorrowKind::from_mutbl(m.into()), ); } adjustment::AutoBorrow::RawPtr(m) => { - debug!("walk_autoref: expr.hir_id={} base_place={:?}", expr.hir_id, base_place); - self.delegate.borrow(base_place, base_place.hir_id, ty::BorrowKind::from_mutbl(m)); } } @@ -527,21 +537,21 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// The core driver for walking a pattern fn walk_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { - debug!("walk_pat(discr_place={:?}, pat={:?})", discr_place, pat); + debug!("expr_use_visitor::walk_pat(discr_place={:?}, pat={:?})", discr_place, pat); let tcx = self.tcx(); let ExprUseVisitor { ref mc, body_owner: _, ref mut delegate } = *self; return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.kind { - debug!("walk_pat: binding place={:?} pat={:?}", place, pat,); + debug!("expr_use_visitor::walk_pat: binding place={:?} pat={:?}", place, pat,); if let Some(bm) = mc.typeck_results.extract_binding_mode(tcx.sess, pat.hir_id, pat.span) { - debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); + debug!("expr_use_visitor::walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); // pat_ty: the type of the binding being produced. let pat_ty = return_if_err!(mc.node_ty(pat.hir_id)); - debug!("walk_pat: pat_ty={:?}", pat_ty); + debug!("expr_use_visitor::walk_pat: pat_ty={:?}", pat_ty); // Each match binding is effectively an assignment to the // binding being produced. @@ -589,7 +599,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing /// closure as the DefId. fn walk_captures(&mut self, closure_expr: &hir::Expr<'_>) { - debug!("walk_captures({:?})", closure_expr); + debug!("expr_use_visitor::walk_captures({:?})", closure_expr); let closure_def_id = self.tcx().hir().local_def_id(closure_expr.hir_id).to_def_id(); let upvars = self.tcx().upvars_mentioned(self.body_owner); diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index a601123c8d055..85e42ffdb71e6 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -237,6 +237,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } crate fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult> { + debug!("cat_expr(expr: {:?})", expr); // This recursion helper avoids going through *too many* // adjustments, since *only* non-overloaded deref recurses. fn helper<'a, 'tcx>( @@ -299,7 +300,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } crate fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> McResult> { - debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr); + debug!("cat_expr_unadjusted: id={} expr={:?}", expr.hir_id, expr); let expr_ty = self.expr_ty(expr)?; match expr.kind { @@ -350,8 +351,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_res(expr.hir_id, expr.span, expr_ty, res) } - hir::ExprKind::Type(ref e, _) => self.cat_expr(&e), - hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) | hir::ExprKind::Assign(..) @@ -378,6 +377,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | hir::ExprKind::InlineAsm(..) | hir::ExprKind::LlvmInlineAsm(..) | hir::ExprKind::Box(..) + | hir::ExprKind::Type(..) | hir::ExprKind::Err => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)), } } @@ -446,7 +446,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr_ty: Ty<'tcx>, ) -> PlaceWithHirId<'tcx> { debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span); - let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()); + let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue(hir_id), Vec::new()); debug!("cat_rvalue ret={:?}", ret); ret } diff --git a/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr b/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr index 8c3463a2832e0..6b1964487f79b 100644 --- a/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr +++ b/src/test/ui/associated-types/associated-types-ICE-when-projecting-out-of-err.stderr @@ -4,6 +4,8 @@ error[E0277]: the trait bound `(): Add` is not satisfied LL | r = r + a; | ^ the trait `Add` is not implemented for `()` -error: aborting due to previous error +error: requires `copy` lang_item + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs b/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs index c139e823c2aef..bd31f1dbd8545 100644 --- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs +++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.rs @@ -1,29 +1,29 @@ // A version of coerce-expect-unsized that uses type ascription. // Doesn't work so far, but supposed to work eventually +// check-pass + #![feature(box_syntax, type_ascription)] use std::fmt::Debug; pub fn main() { - let _ = box { [1, 2, 3] }: Box<[i32]>; //~ ERROR mismatched types - let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; //~ ERROR mismatched types + let _ = box { [1, 2, 3] }: Box<[i32]>; + let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>; - //~^ ERROR mismatched types - let _ = box { |x| (x as u8) }: Box _>; //~ ERROR mismatched types - let _ = box if true { false } else { true }: Box; //~ ERROR mismatched types - let _ = box match true { true => 'a', false => 'b' }: Box; //~ ERROR mismatched types + let _ = box { |x| (x as u8) }: Box _>; + let _ = box if true { false } else { true }: Box; + let _ = box match true { true => 'a', false => 'b' }: Box; - let _ = &{ [1, 2, 3] }: &[i32]; //~ ERROR mismatched types - let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; //~ ERROR mismatched types + let _ = &{ [1, 2, 3] }: &[i32]; + let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32]; - //~^ ERROR mismatched types - let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; //~ ERROR mismatched types - let _ = &if true { false } else { true }: &dyn Debug; //~ ERROR mismatched types - let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; //~ ERROR mismatched types + let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; + let _ = &if true { false } else { true }: &dyn Debug; + let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; - let _ = Box::new([1, 2, 3]): Box<[i32]>; //~ ERROR mismatched types - let _ = Box::new(|x| (x as u8)): Box _>; //~ ERROR mismatched types + let _ = Box::new([1, 2, 3]): Box<[i32]>; + let _ = Box::new(|x| (x as u8)): Box _>; let _ = vec![ Box::new(|x| (x as u8)), diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr deleted file mode 100644 index f0109f22a2bc1..0000000000000 --- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr +++ /dev/null @@ -1,129 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:9:13 - | -LL | let _ = box { [1, 2, 3] }: Box<[i32]>; - | ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected struct `Box<[i32]>` - found struct `Box<[i32; 3]>` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:10:13 - | -LL | let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected struct `Box<[i32]>` - found struct `Box<[i32; 3]>` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:11:13 - | -LL | let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected struct `Box<[i32]>` - found struct `Box<[i32; 3]>` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:13:13 - | -LL | let _ = box { |x| (x as u8) }: Box _>; - | ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure - | - = note: expected struct `Box u8>` - found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:14:13 - | -LL | let _ = box if true { false } else { true }: Box; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool` - | - = note: expected struct `Box` - found struct `Box` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:15:13 - | -LL | let _ = box match true { true => 'a', false => 'b' }: Box; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char` - | - = note: expected struct `Box` - found struct `Box` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:17:13 - | -LL | let _ = &{ [1, 2, 3] }: &[i32]; - | ^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected reference `&[i32]` - found reference `&[i32; 3]` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:18:13 - | -LL | let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected reference `&[i32]` - found reference `&[i32; 3]` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:19:13 - | -LL | let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected reference `&[i32]` - found reference `&[i32; 3]` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:21:13 - | -LL | let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; - | ^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure - | - = note: expected reference `&dyn Fn(i32) -> u8` - found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:22:13 - | -LL | let _ = &if true { false } else { true }: &dyn Debug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool` - | - = note: expected reference `&dyn Debug` - found reference `&bool` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:23:13 - | -LL | let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char` - | - = note: expected reference `&dyn Debug` - found reference `&char` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:25:13 - | -LL | let _ = Box::new([1, 2, 3]): Box<[i32]>; - | ^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]` - | - = note: expected struct `Box<[i32]>` - found struct `Box<[i32; 3]>` - -error[E0308]: mismatched types - --> $DIR/coerce-expect-unsized-ascribed.rs:26:13 - | -LL | let _ = Box::new(|x| (x as u8)): Box _>; - | ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure - | - = note: expected struct `Box u8>` - found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>` - -error: aborting due to 14 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/type-ascription/coerce-array-repeat-in-fn-arg.rs b/src/test/ui/coercion/type-ascription/coerce-array-repeat-in-fn-arg.rs new file mode 100644 index 0000000000000..00d9de2f0f941 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-array-repeat-in-fn-arg.rs @@ -0,0 +1,9 @@ +#![feature(type_ascription)] + +fn foo(_arg : [&[u32];3]) {} + +fn main() { + let arr = [4,5,6]; + foo([&arr : &[u32]; 3]); + //~^ ERROR type ascriptions are not +} diff --git a/src/test/ui/coercion/type-ascription/coerce-array-repeat-in-fn-arg.stderr b/src/test/ui/coercion/type-ascription/coerce-array-repeat-in-fn-arg.stderr new file mode 100644 index 0000000000000..213f7295a8477 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-array-repeat-in-fn-arg.stderr @@ -0,0 +1,8 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/coerce-array-repeat-in-fn-arg.rs:7:8 + | +LL | foo([&arr : &[u32]; 3]); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/coercion/type-ascription/coerce-enum-variant.rs b/src/test/ui/coercion/type-ascription/coerce-enum-variant.rs new file mode 100644 index 0000000000000..01ec9ec12379b --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-enum-variant.rs @@ -0,0 +1,12 @@ +#![feature(type_ascription)] + +enum Foo<'a> { + A((u32, &'a [u32])), + B((u32, &'a [u32; 4])), +} + +fn main() { + let arr = [4,5,6]; + let temp = Foo::A((10, &arr : &[u32])); + //~^ ERROR type ascriptions are not +} diff --git a/src/test/ui/coercion/type-ascription/coerce-enum-variant.stderr b/src/test/ui/coercion/type-ascription/coerce-enum-variant.stderr new file mode 100644 index 0000000000000..aada2ca1c645b --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-enum-variant.stderr @@ -0,0 +1,8 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/coerce-enum-variant.rs:10:26 + | +LL | let temp = Foo::A((10, &arr : &[u32])); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/coercion/type-ascription/coerce-nested-tuple-in-let-stmt.rs b/src/test/ui/coercion/type-ascription/coerce-nested-tuple-in-let-stmt.rs new file mode 100644 index 0000000000000..6477e143f1476 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-nested-tuple-in-let-stmt.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(type_ascription)] + +use std::any::type_name; +use std::assert_eq; + +fn type_of(_: T) -> &'static str { + type_name::() +} + +fn main() { + let arr = [5,6,7]; + let tup = (5, (3, (12, &arr : &[u32])), &arr : &[u32]); + assert_eq!(type_of(tup), "(i32, (i32, (i32, &[u32])), &[u32])"); +} diff --git a/src/test/ui/coercion/type-ascription/coerce-return-expr.rs b/src/test/ui/coercion/type-ascription/coerce-return-expr.rs new file mode 100644 index 0000000000000..b9b7c691e14d7 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-return-expr.rs @@ -0,0 +1,12 @@ +#![feature(type_ascription)] + +fn foo<'a>(arg : (u32, (u32, &'a [u32; 3]))) -> (u32, (u32, &'a [u32])) { + arg : (u32, (u32, &[u32])) + //~^ ERROR: mismatched types +} + +fn main() { + let arr = [4,5,6]; + let tup = (3, (9, &arr)); + let result = foo(tup); +} diff --git a/src/test/ui/coercion/type-ascription/coerce-return-expr.stderr b/src/test/ui/coercion/type-ascription/coerce-return-expr.stderr new file mode 100644 index 0000000000000..0a6d26cfa44a6 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-return-expr.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/coerce-return-expr.rs:4:3 + | +LL | arg : (u32, (u32, &[u32])) + | ^^^ expected slice `[u32]`, found array `[u32; 3]` + | + = note: expected tuple `(_, (_, &[u32]))` + found tuple `(_, (_, &'a [u32; 3]))` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/coercion/type-ascription/coerce-struct-fields-pass-in-let-stmt.rs b/src/test/ui/coercion/type-ascription/coerce-struct-fields-pass-in-let-stmt.rs new file mode 100644 index 0000000000000..49ef6b097d742 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-struct-fields-pass-in-let-stmt.rs @@ -0,0 +1,28 @@ +// Here we test for coercions in struct fields of nested type ascriptions +// inside a tuple using an unsized coercion and a coercion from &mut -> & + +#![feature(type_ascription)] + +use std::any::type_name; +use std::assert_eq; + +fn type_of(_: T) -> &'static str { + type_name::() +} + +struct Foo<'a, 'b, T1, T2> { + _a : (T1, (T1, &'a [T1]), &'b T2), +} + +struct Bar { + _b : u32, +} + +fn main() { + let mut bar = Bar {_b : 26}; + let arr = [4,5,6]; + let tup = (9, (3, &arr : &[u32]), &mut bar); + assert_eq!(type_of(tup), "(i32, (i32, &[u32]), &mut coerce_struct_fields_pass_in_let_stmt::Bar)"); + let _ = Foo { _a : (9, (3, &arr : &[u32]), &mut bar) }; + //~^ ERROR type ascriptions are not +} diff --git a/src/test/ui/coercion/type-ascription/coerce-struct-fields-pass-in-let-stmt.stderr b/src/test/ui/coercion/type-ascription/coerce-struct-fields-pass-in-let-stmt.stderr new file mode 100644 index 0000000000000..757020b9ab46c --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-struct-fields-pass-in-let-stmt.stderr @@ -0,0 +1,8 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/coerce-struct-fields-pass-in-let-stmt.rs:26:30 + | +LL | let _ = Foo { _a : (9, (3, &arr : &[u32]), &mut bar) }; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/coercion/type-ascription/coerce-to-unsized-in-return-expr.rs b/src/test/ui/coercion/type-ascription/coerce-to-unsized-in-return-expr.rs new file mode 100644 index 0000000000000..6127b3506a1b3 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-to-unsized-in-return-expr.rs @@ -0,0 +1,11 @@ +#![feature(type_ascription)] + +fn foo<'a>(arg : &'a [u32; 3]) -> &'a [u32] { + arg : &[u32] + //~^ ERROR type ascriptions are not +} + +fn main() { + let arr = [4,5,6]; + let _ = foo(&arr); +} diff --git a/src/test/ui/coercion/type-ascription/coerce-to-unsized-in-return-expr.stderr b/src/test/ui/coercion/type-ascription/coerce-to-unsized-in-return-expr.stderr new file mode 100644 index 0000000000000..08c14db54ea6d --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-to-unsized-in-return-expr.stderr @@ -0,0 +1,8 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/coerce-to-unsized-in-return-expr.rs:4:3 + | +LL | arg : &[u32] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/coercion/type-ascription/coerce-union-field.rs b/src/test/ui/coercion/type-ascription/coerce-union-field.rs new file mode 100644 index 0000000000000..fbd8d5e243663 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-union-field.rs @@ -0,0 +1,14 @@ +#![feature(type_ascription)] + +union Foo<'a> { + f1: (&'a u32, (u32, &'a [u32])), + _f2: u32, +} + +fn main() { + let arr = [4,5,6]; + let x = &mut 26; + let _ = Foo { f1: (x : &u32, (5, &arr : &[u32])) }; + //~^ ERROR type ascriptions + //~^^ ERROR type ascriptions +} diff --git a/src/test/ui/coercion/type-ascription/coerce-union-field.stderr b/src/test/ui/coercion/type-ascription/coerce-union-field.stderr new file mode 100644 index 0000000000000..ee6c573ee92b5 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/coerce-union-field.stderr @@ -0,0 +1,19 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/coerce-union-field.rs:11:22 + | +LL | let _ = Foo { f1: (x : &u32, (5, &arr : &[u32])) }; + | ^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let x: &u32 = &mut 26; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/coerce-union-field.rs:11:36 + | +LL | let _ = Foo { f1: (x : &u32, (5, &arr : &[u32])) }; + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/coercion/type-ascription/unsound-type-ascription-coercion.rs b/src/test/ui/coercion/type-ascription/unsound-type-ascription-coercion.rs new file mode 100644 index 0000000000000..bb858182f0cee --- /dev/null +++ b/src/test/ui/coercion/type-ascription/unsound-type-ascription-coercion.rs @@ -0,0 +1,17 @@ +#![feature(type_ascription)] + +fn f() { + let mut x: &'static u32 = &22; + let y = &44; + foo(x, y); +} + +fn foo<'a, 'b>(arg1 : &'a u32, arg2 : &'b u32) { + let p = &mut (arg1 : &'b u32); + //~^ ERROR: type ascriptions are not allowed + *p = arg2; +} + +fn main() { + f(); +} diff --git a/src/test/ui/coercion/type-ascription/unsound-type-ascription-coercion.stderr b/src/test/ui/coercion/type-ascription/unsound-type-ascription-coercion.stderr new file mode 100644 index 0000000000000..8729ac5723e37 --- /dev/null +++ b/src/test/ui/coercion/type-ascription/unsound-type-ascription-coercion.stderr @@ -0,0 +1,8 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/unsound-type-ascription-coercion.rs:10:16 + | +LL | let p = &mut (arg1 : &'b u32); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/mir/mir_ascription_coercion.rs b/src/test/ui/mir/mir_ascription_coercion.rs index 0ebd20e97d7ef..be2f124d3aaab 100644 --- a/src/test/ui/mir/mir_ascription_coercion.rs +++ b/src/test/ui/mir/mir_ascription_coercion.rs @@ -1,4 +1,3 @@ -// run-pass // Tests that the result of type ascription has adjustments applied #![feature(type_ascription)] @@ -7,4 +6,5 @@ fn main() { let x = [1, 2, 3]; // The RHS should coerce to &[i32] let _y : &[i32] = &x : &[i32; 3]; + //~^ ERROR type ascriptions } diff --git a/src/test/ui/mir/mir_ascription_coercion.stderr b/src/test/ui/mir/mir_ascription_coercion.stderr new file mode 100644 index 0000000000000..8a454f1891d8d --- /dev/null +++ b/src/test/ui/mir/mir_ascription_coercion.stderr @@ -0,0 +1,8 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/mir_ascription_coercion.rs:8:23 + | +LL | let _y : &[i32] = &x : &[i32; 3]; + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs index 101b5cfabb3d0..cbab403ec231d 100644 --- a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs +++ b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.rs @@ -3,5 +3,6 @@ fn main() { let x = 22_u32; - let y: &u32 = &x: &'static u32; //~ ERROR E0597 + let y: &u32 = &x: &'static u32; + //~^ ERROR type ascriptions are not } diff --git a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr index 133bbef52311d..6f59588f91b2d 100644 --- a/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr +++ b/src/test/ui/nll/user-annotations/type_ascription_static_lifetime.stderr @@ -1,14 +1,8 @@ -error[E0597]: `x` does not live long enough +error: type ascriptions are not allowed in lvalue contexts --> $DIR/type_ascription_static_lifetime.rs:6:19 | -LL | let y: &u32 = &x: &'static u32; - | ^^-------------- - | | - | borrowed value does not live long enough - | type annotation requires that `x` is borrowed for `'static` -LL | } - | - `x` dropped here while still borrowed +LL | let y: &u32 = &x: &'static u32; + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr b/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr index 2bae12efbde38..6c07537cd634b 100644 --- a/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr +++ b/src/test/ui/panic-handler/panic-handler-requires-panic-info.stderr @@ -1,4 +1,6 @@ error: language item required, but not found: `panic_info` -error: aborting due to previous error +error: requires `copy` lang_item + +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index e725aa5d73d1f..f20ee66f8f9fd 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -11,6 +11,7 @@ pub fn index_after_as_cast() { //~^ ERROR: casts cannot be followed by indexing vec![1, 2, 3]: Vec[0]; //~^ ERROR: casts cannot be followed by indexing + //~| ERROR type ascriptions are not } pub fn index_after_cast_to_index() { @@ -18,6 +19,7 @@ pub fn index_after_cast_to_index() { //~^ ERROR: casts cannot be followed by indexing (&[0i32]): &[i32; 1][0]; //~^ ERROR: casts cannot be followed by indexing + //~| ERROR type ascriptions are not } pub fn cast_after_cast() { @@ -25,9 +27,11 @@ pub fn cast_after_cast() { } if 5u64: u64: u64 == 0u64 { + //~^ ERROR type ascriptions are not } let _ = 5u64: u64: u64 as u8 as i8 == 9i8; + //~^ ERROR type ascriptions are not let _ = 0i32: i32: i32; let _ = 0 as i32: i32; let _ = 0i32: i32 as i32; @@ -84,7 +88,8 @@ pub fn complex() { if true { 33 } else { 44 } as i32.max(0), //~^ ERROR: casts cannot be followed by a method call if true { 33 } else { 44 }: i32.max(0) - //~^ ERROR: casts cannot be followed by a method call + //~^ ERROR type ascriptions are not + //~| ERROR: casts cannot be followed by a method call ); } @@ -94,6 +99,7 @@ pub fn in_condition() { } if 5u64: u64.max(0) == 0 { //~^ ERROR: casts cannot be followed by a method call + //~| ERROR type ascriptions are not } } @@ -105,6 +111,7 @@ pub fn inside_block() { let _ = if true { 5u64: u64.max(0) == 0 //~^ ERROR: casts cannot be followed by a method call + //~| ERROR type ascriptions are not } else { false }; } @@ -113,6 +120,7 @@ static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); //~^ ERROR: casts cannot be followed by indexing +//~| ERROR type ascriptions are not pub fn cast_then_try() -> Result { @@ -120,6 +128,7 @@ pub fn cast_then_try() -> Result { //~^ ERROR: casts cannot be followed by ? Err(0u64): Result?; //~^ ERROR: casts cannot be followed by ? + //~| ERROR type ascriptions are not Ok(1) } diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index 9ccf17a6cb10e..95cebb2150f7a 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -21,7 +21,7 @@ LL | (vec![1, 2, 3]: Vec)[0]; | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:17:5 + --> $DIR/issue-35813-postfix-after-cast.rs:18:5 | LL | (&[0]) as &[i32][0]; | ^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | ((&[0]) as &[i32])[0]; | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:19:5 + --> $DIR/issue-35813-postfix-after-cast.rs:20:5 | LL | (&[0i32]): &[i32; 1][0]; | ^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | ((&[0i32]): &[i32; 1])[0]; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:39:13 + --> $DIR/issue-35813-postfix-after-cast.rs:43:13 | LL | let _ = 0i32: i32: i32.count_ones(); | ^^^^^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | let _ = (0i32: i32: i32).count_ones(); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:41:13 + --> $DIR/issue-35813-postfix-after-cast.rs:45:13 | LL | let _ = 0 as i32: i32.count_ones(); | ^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | let _ = (0 as i32: i32).count_ones(); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:43:13 + --> $DIR/issue-35813-postfix-after-cast.rs:47:13 | LL | let _ = 0i32: i32 as i32.count_ones(); | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | let _ = (0i32: i32 as i32).count_ones(); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:45:13 + --> $DIR/issue-35813-postfix-after-cast.rs:49:13 | LL | let _ = 0 as i32 as i32.count_ones(); | ^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | let _ = (0 as i32 as i32).count_ones(); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:47:13 + --> $DIR/issue-35813-postfix-after-cast.rs:51:13 | LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ LL | let _ = (0i32: i32: i32 as u32 as i32).count_ones(); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:49:13 + --> $DIR/issue-35813-postfix-after-cast.rs:53:13 | LL | let _ = 0i32: i32.count_ones(): u32; | ^^^^^^^^^ @@ -109,7 +109,7 @@ LL | let _ = (0i32: i32).count_ones(): u32; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:51:13 + --> $DIR/issue-35813-postfix-after-cast.rs:55:13 | LL | let _ = 0 as i32.count_ones(): u32; | ^^^^^^^^ @@ -120,7 +120,7 @@ LL | let _ = (0 as i32).count_ones(): u32; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:53:13 + --> $DIR/issue-35813-postfix-after-cast.rs:57:13 | LL | let _ = 0i32: i32.count_ones() as u32; | ^^^^^^^^^ @@ -131,7 +131,7 @@ LL | let _ = (0i32: i32).count_ones() as u32; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:55:13 + --> $DIR/issue-35813-postfix-after-cast.rs:59:13 | LL | let _ = 0 as i32.count_ones() as u32; | ^^^^^^^^ @@ -142,7 +142,7 @@ LL | let _ = (0 as i32).count_ones() as u32; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:57:13 + --> $DIR/issue-35813-postfix-after-cast.rs:61:13 | LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; | ^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL | let _ = (0i32: i32: i32).count_ones() as u32 as i32; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:62:13 + --> $DIR/issue-35813-postfix-after-cast.rs:66:13 | LL | let _ = 0 | _____________^ @@ -167,7 +167,7 @@ LL | as i32) | error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:70:18 + --> $DIR/issue-35813-postfix-after-cast.rs:74:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL | let x: i32 = (&vec![1, 2, 3] as &Vec)[0]; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:75:5 + --> $DIR/issue-35813-postfix-after-cast.rs:79:5 | LL | 0 as i32.max(0); | ^^^^^^^^ @@ -189,7 +189,7 @@ LL | (0 as i32).max(0); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:77:5 + --> $DIR/issue-35813-postfix-after-cast.rs:81:5 | LL | 0: i32.max(0); | ^^^^^^ @@ -200,7 +200,7 @@ LL | (0: i32).max(0); | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:92:8 + --> $DIR/issue-35813-postfix-after-cast.rs:97:8 | LL | if 5u64 as i32.max(0) == 0 { | ^^^^^^^^^^^ @@ -211,7 +211,7 @@ LL | if (5u64 as i32).max(0) == 0 { | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:95:8 + --> $DIR/issue-35813-postfix-after-cast.rs:100:8 | LL | if 5u64: u64.max(0) == 0 { | ^^^^^^^^^ @@ -222,7 +222,7 @@ LL | if (5u64: u64).max(0) == 0 { | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:102:9 + --> $DIR/issue-35813-postfix-after-cast.rs:108:9 | LL | 5u64 as u32.max(0) == 0 | ^^^^^^^^^^^ @@ -233,7 +233,7 @@ LL | (5u64 as u32).max(0) == 0 | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:106:9 + --> $DIR/issue-35813-postfix-after-cast.rs:112:9 | LL | 5u64: u64.max(0) == 0 | ^^^^^^^^^ @@ -244,7 +244,7 @@ LL | (5u64: u64).max(0) == 0 | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:111:24 + --> $DIR/issue-35813-postfix-after-cast.rs:118:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); | ^^^^^^^^^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:114:25 + --> $DIR/issue-35813-postfix-after-cast.rs:121:25 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -266,7 +266,7 @@ LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]); | ^ ^ error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:119:5 + --> $DIR/issue-35813-postfix-after-cast.rs:127:5 | LL | Err(0u64) as Result?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL | (Err(0u64) as Result)?; | ^ ^ error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:121:5 + --> $DIR/issue-35813-postfix-after-cast.rs:129:5 | LL | Err(0u64): Result?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -288,7 +288,7 @@ LL | (Err(0u64): Result)?; | ^ ^ error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:145:5 + --> $DIR/issue-35813-postfix-after-cast.rs:154:5 | LL | drop as fn(u8)(0); | ^^^^^^^^^^^^^^ @@ -299,7 +299,7 @@ LL | (drop as fn(u8))(0); | ^ ^ error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:147:5 + --> $DIR/issue-35813-postfix-after-cast.rs:156:5 | LL | drop_ptr: fn(u8)(0); | ^^^^^^^^^^^^^^^^ @@ -310,7 +310,7 @@ LL | (drop_ptr: fn(u8))(0); | ^ ^ error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:152:5 + --> $DIR/issue-35813-postfix-after-cast.rs:161:5 | LL | Box::pin(noop()) as Pin>>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -321,7 +321,7 @@ LL | (Box::pin(noop()) as Pin>>).await; | ^ ^ error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:155:5 + --> $DIR/issue-35813-postfix-after-cast.rs:164:5 | LL | Box::pin(noop()): Pin>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -332,7 +332,7 @@ LL | (Box::pin(noop()): Pin>).await; | ^ ^ error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:167:5 + --> $DIR/issue-35813-postfix-after-cast.rs:176:5 | LL | Foo::default() as Foo.bar; | ^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +343,7 @@ LL | (Foo::default() as Foo).bar; | ^ ^ error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:169:5 + --> $DIR/issue-35813-postfix-after-cast.rs:178:5 | LL | Foo::default(): Foo.bar; | ^^^^^^^^^^^^^^^^^^^ @@ -354,7 +354,7 @@ LL | (Foo::default(): Foo).bar; | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:84:9 + --> $DIR/issue-35813-postfix-after-cast.rs:88:9 | LL | if true { 33 } else { 44 } as i32.max(0), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -365,7 +365,7 @@ LL | (if true { 33 } else { 44 } as i32).max(0), | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:86:9 + --> $DIR/issue-35813-postfix-after-cast.rs:90:9 | LL | if true { 33 } else { 44 }: i32.max(0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -376,17 +376,71 @@ LL | (if true { 33 } else { 44 }: i32).max(0) | ^ ^ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:131:13 + --> $DIR/issue-35813-postfix-after-cast.rs:140:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:133:15 + --> $DIR/issue-35813-postfix-after-cast.rs:142:15 | LL | drop_ptr: F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 36 previous errors +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:121:25 + | +LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:12:5 + | +LL | vec![1, 2, 3]: Vec[0]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:20:5 + | +LL | (&[0i32]): &[i32; 1][0]; + | ^^^^^^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:29:8 + | +LL | if 5u64: u64: u64 == 0u64 { + | ^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:33:13 + | +LL | let _ = 5u64: u64: u64 as u8 as i8 == 9i8; + | ^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:90:9 + | +LL | if true { 33 } else { 44 }: i32.max(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:100:8 + | +LL | if 5u64: u64.max(0) == 0 { + | ^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:112:9 + | +LL | 5u64: u64.max(0) == 0 + | ^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/issue-35813-postfix-after-cast.rs:129:5 + | +LL | Err(0u64): Result?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 45 previous errors For more information about this error, try `rustc --explain E0214`. diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs index a814003aebf20..76882e5a6c6bb 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -1,4 +1,3 @@ -// check-pass // Check that taking the address of a place that contains a dereference is // allowed. #![feature(raw_ref_op, type_ascription)] @@ -19,6 +18,12 @@ fn main() { let x = 0; let ascribe_ref = &raw const (x: i32); + //~^ ERROR type ascriptions are not + //~| ERROR cannot take address of a temporary let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + //~^ ERROR type ascriptions are not + //~| ERROR cannot take address of a temporary let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); + //~^ ERROR type ascriptions are not + //~| ERROR cannot take address of a temporary } diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr new file mode 100644 index 0000000000000..25cdb6666136f --- /dev/null +++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr @@ -0,0 +1,44 @@ +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp-deref.rs:20:34 + | +LL | let ascribe_ref = &raw const (x: i32); + | ^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp-deref.rs:23:36 + | +LL | let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^ temporary value + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-ref-temp-deref.rs:26:42 + | +LL | let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); + | ^^^^^^^^^^^^^^^^^^^ temporary value + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp-deref.rs:20:34 + | +LL | let ascribe_ref = &raw const (x: i32); + | ^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let x: i32 = 0; + | ^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp-deref.rs:23:36 + | +LL | let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp-deref.rs:26:42 + | +LL | let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0745`. diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.rs b/src/test/ui/raw-ref-op/raw-ref-temp.rs index 32df56468da17..f322b72410bb1 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp.rs @@ -23,9 +23,19 @@ fn main() { let index_ref = &raw const ARRAY[0]; //~ ERROR cannot take address let mut_index_ref = &raw mut ARRAY[1]; //~ ERROR cannot take address - let ref_ascribe = &raw const (2: i32); //~ ERROR cannot take address - let mut_ref_ascribe = &raw mut (3: i32); //~ ERROR cannot take address - - let ascribe_field_ref = &raw const (PAIR.0: i32); //~ ERROR cannot take address - let ascribe_index_ref = &raw mut (ARRAY[0]: i32); //~ ERROR cannot take address + let ref_ascribe = &raw const (2: i32); + //~^ ERROR cannot take address + //~| ERROR type ascriptions are not + + let mut_ref_ascribe = &raw mut (3: i32); + //~^ ERROR cannot take address + //~| ERROR type ascriptions are not + + let ascribe_field_ref = &raw const (PAIR.0: i32); + //~^ ERROR cannot take address + //~| ERROR type ascriptions are not + + let ascribe_index_ref = &raw mut (ARRAY[0]: i32); + //~^ ERROR cannot take address + //~| ERROR type ascriptions are not } diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.stderr b/src/test/ui/raw-ref-op/raw-ref-temp.stderr index 80dea76d5953b..17186c445d1e4 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.stderr +++ b/src/test/ui/raw-ref-op/raw-ref-temp.stderr @@ -77,23 +77,47 @@ LL | let ref_ascribe = &raw const (2: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:27:36 + --> $DIR/raw-ref-temp.rs:30:36 | LL | let mut_ref_ascribe = &raw mut (3: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:29:40 + --> $DIR/raw-ref-temp.rs:34:40 | LL | let ascribe_field_ref = &raw const (PAIR.0: i32); | ^^^^^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:30:38 + --> $DIR/raw-ref-temp.rs:38:38 | LL | let ascribe_index_ref = &raw mut (ARRAY[0]: i32); | ^^^^^^^^^^^^^^^ temporary value -error: aborting due to 16 previous errors +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp.rs:26:34 + | +LL | let ref_ascribe = &raw const (2: i32); + | ^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp.rs:30:36 + | +LL | let mut_ref_ascribe = &raw mut (3: i32); + | ^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp.rs:34:40 + | +LL | let ascribe_field_ref = &raw const (PAIR.0: i32); + | ^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/raw-ref-temp.rs:38:38 + | +LL | let ascribe_index_ref = &raw mut (ARRAY[0]: i32); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0745`. diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.rs b/src/test/ui/suggestions/type-ascription-instead-of-let.rs index 0e1c307502728..9830119feb832 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-let.rs +++ b/src/test/ui/suggestions/type-ascription-instead-of-let.rs @@ -4,6 +4,7 @@ fn main() { let closure_annotated = |value: i32| -> i32 { temp: i32 = fun(5i32); //~^ ERROR cannot find value `temp` in this scope + //~| ERROR invalid left-hand side of assignment temp + value + 1 //~^ ERROR cannot find value `temp` in this scope }; diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.stderr b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr index 92e4b5798c889..868837ecb0fc1 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-let.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr @@ -8,11 +8,20 @@ LL | temp: i32 = fun(5i32); | help: maybe you meant to write an assignment here: `let temp` error[E0425]: cannot find value `temp` in this scope - --> $DIR/type-ascription-instead-of-let.rs:7:9 + --> $DIR/type-ascription-instead-of-let.rs:8:9 | LL | temp + value + 1 | ^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0070]: invalid left-hand side of assignment + --> $DIR/type-ascription-instead-of-let.rs:5:19 + | +LL | temp: i32 = fun(5i32); + | --------- ^ + | | + | cannot assign to this expression + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0070, E0425. +For more information about an error, try `rustc --explain E0070`. diff --git a/src/test/ui/type-ascription.rs b/src/test/ui/type-ascription.rs index 7adb074428ce9..9df8222beed0d 100644 --- a/src/test/ui/type-ascription.rs +++ b/src/test/ui/type-ascription.rs @@ -1,5 +1,3 @@ -// run-pass - #![allow(dead_code)] #![allow(unused_variables)] // Type ascription doesn't lead to unsoundness @@ -17,6 +15,7 @@ struct S { fn main() { assert_eq!(C1.into(): i32, 10); + //~^ ERROR type ascriptions are not assert_eq!(C2[0], 1); let s = S { a: 10: u8 }; @@ -29,11 +28,15 @@ fn main() { let a = 1: u8; let b = a.into(): u16; assert_eq!(v[a.into(): usize], 2); + //~^ ERROR type ascriptions are not assert_eq!(mem::size_of_val(&a), 1); assert_eq!(mem::size_of_val(&b), 2); assert_eq!(b, 1: u16); + //~^ ERROR type ascriptions are not let mut v = Vec::new(); v: Vec = vec![1, 2, 3]; // Place expression type ascription + //~^ ERROR invalid left-hand side of assignment + //~| ERROR type ascriptions are not assert_eq!(v, [1u8, 2, 3]); } diff --git a/src/test/ui/type-ascription.stderr b/src/test/ui/type-ascription.stderr new file mode 100644 index 0000000000000..c8b7347d13836 --- /dev/null +++ b/src/test/ui/type-ascription.stderr @@ -0,0 +1,35 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/type-ascription.rs:38:16 + | +LL | v: Vec = vec![1, 2, 3]; // Place expression type ascription + | ---------- ^ + | | + | cannot assign to this expression + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription.rs:17:16 + | +LL | assert_eq!(C1.into(): i32, 10); + | ^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription.rs:30:18 + | +LL | assert_eq!(v[a.into(): usize], 2); + | ^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription.rs:34:19 + | +LL | assert_eq!(b, 1: u16); + | ^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription.rs:38:5 + | +LL | v: Vec = vec![1, 2, 3]; // Place expression type ascription + | ^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/type-ascription/as_ref.rs b/src/test/ui/type-ascription/as_ref.rs new file mode 100644 index 0000000000000..c182dca2b5347 --- /dev/null +++ b/src/test/ui/type-ascription/as_ref.rs @@ -0,0 +1,27 @@ +#![feature(type_ascription)] + +use std::convert::AsRef; + +struct Foo { + a : u32, +} + +impl AsRef for Foo { + fn as_ref(&self) -> &Foo { + &self + } +} + +fn main() { + let foo = Foo { a : 1 }; + let r = &mut foo; + + let x = (r : &Foo).as_ref(); + //~^ ERROR: type ascriptions are not + + let another_one = (r : &Foo).as_ref().a; + //~^ ERROR: type ascriptions are not + + let last_one = &*((r : &Foo).as_ref()); + //~^ ERROR: type ascriptions are not +} diff --git a/src/test/ui/type-ascription/as_ref.stderr b/src/test/ui/type-ascription/as_ref.stderr new file mode 100644 index 0000000000000..1bce563e8b1ff --- /dev/null +++ b/src/test/ui/type-ascription/as_ref.stderr @@ -0,0 +1,35 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/as_ref.rs:19:11 + | +LL | let x = (r : &Foo).as_ref(); + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/as_ref.rs:22:21 + | +LL | let another_one = (r : &Foo).as_ref().a; + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/as_ref.rs:25:21 + | +LL | let last_one = &*((r : &Foo).as_ref()); + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/type-ascription/assign.rs b/src/test/ui/type-ascription/assign.rs new file mode 100644 index 0000000000000..097af47f951d1 --- /dev/null +++ b/src/test/ui/type-ascription/assign.rs @@ -0,0 +1,10 @@ +#![feature(type_ascription)] + +fn main() { + let arr1 = [4,5,6]; + let arr2 = [2,2,2]; + let mut x = &arr1; + x : &[u32] = &arr2; + //~^ ERROR type ascriptions are not allowed + //~| ERROR invalid left-hand side of assignment +} diff --git a/src/test/ui/type-ascription/assign.stderr b/src/test/ui/type-ascription/assign.stderr new file mode 100644 index 0000000000000..2a556bdaee63b --- /dev/null +++ b/src/test/ui/type-ascription/assign.stderr @@ -0,0 +1,17 @@ +error[E0070]: invalid left-hand side of assignment + --> $DIR/assign.rs:7:14 + | +LL | x : &[u32] = &arr2; + | ---------- ^ + | | + | cannot assign to this expression + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/assign.rs:7:3 + | +LL | x : &[u32] = &arr2; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/type-ascription/automatic_reborrows.rs b/src/test/ui/type-ascription/automatic_reborrows.rs new file mode 100644 index 0000000000000..ef85068d7f3cc --- /dev/null +++ b/src/test/ui/type-ascription/automatic_reborrows.rs @@ -0,0 +1,21 @@ +#![feature(type_ascription)] + +struct Foo<'a> { + a : &'a [u32], +} + +impl Foo<'_> { + fn foo_that<'a>(&self, p : &'a [u32]) {} +} + + +fn main() { + let arr = [4,5,6]; + let r = &arr; + let foo = Foo {a : (r : &[u32]) }; + //~^ ERROR: type ascriptions are not + + let fooer = Foo {a : r}; + fooer.foo_that(r : &[u32]); + //~^ ERROR: type ascriptions are not +} diff --git a/src/test/ui/type-ascription/automatic_reborrows.stderr b/src/test/ui/type-ascription/automatic_reborrows.stderr new file mode 100644 index 0000000000000..69e1b7d668c98 --- /dev/null +++ b/src/test/ui/type-ascription/automatic_reborrows.stderr @@ -0,0 +1,24 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/automatic_reborrows.rs:15:22 + | +LL | let foo = Foo {a : (r : &[u32]) }; + | ^^^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &[u32] = &arr; + | ^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/automatic_reborrows.rs:19:18 + | +LL | fooer.foo_that(r : &[u32]); + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &[u32] = &arr; + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/type-ascription/autoref-method.rs b/src/test/ui/type-ascription/autoref-method.rs new file mode 100644 index 0000000000000..45f15e2550814 --- /dev/null +++ b/src/test/ui/type-ascription/autoref-method.rs @@ -0,0 +1,14 @@ +#![feature(type_ascription)] + +struct Foo {} + +impl Foo { + fn foo(&self) {} +} + +fn main() { + let mut fooer = Foo {}; + let x = &mut fooer; + (x : &Foo).foo(); + //~^ ERROR: type ascriptions are not allowed +} diff --git a/src/test/ui/type-ascription/autoref-method.stderr b/src/test/ui/type-ascription/autoref-method.stderr new file mode 100644 index 0000000000000..83321e3baaf53 --- /dev/null +++ b/src/test/ui/type-ascription/autoref-method.stderr @@ -0,0 +1,13 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/autoref-method.rs:12:3 + | +LL | (x : &Foo).foo(); + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let x: &Foo = &mut fooer; + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-ascription/borrow.rs b/src/test/ui/type-ascription/borrow.rs new file mode 100644 index 0000000000000..bb9815658fb14 --- /dev/null +++ b/src/test/ui/type-ascription/borrow.rs @@ -0,0 +1,21 @@ +#![feature(type_ascription)] + +struct Foo { + a : u32, +} + +fn main() { + let foo = Foo { a : 1 }; + let r = &mut foo; + + let x = &(r : &Foo); + //~^ ERROR: type ascriptions are not + + let another_one = &(r : &Foo).a; + //~^ ERROR: type ascriptions are not + + let arr = [4,5,6]; + let arr_ref = &arr; + let ref last_one = &(arr_ref : &[u32])[1]; + //~^ ERROR: type ascriptions are not +} diff --git a/src/test/ui/type-ascription/borrow.stderr b/src/test/ui/type-ascription/borrow.stderr new file mode 100644 index 0000000000000..59cfb2744103c --- /dev/null +++ b/src/test/ui/type-ascription/borrow.stderr @@ -0,0 +1,35 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/borrow.rs:11:12 + | +LL | let x = &(r : &Foo); + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/borrow.rs:14:22 + | +LL | let another_one = &(r : &Foo).a; + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/borrow.rs:19:23 + | +LL | let ref last_one = &(arr_ref : &[u32])[1]; + | ^^^^^^^^^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let arr_ref: &[u32] = &arr; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/type-ascription/ref-def.rs b/src/test/ui/type-ascription/ref-def.rs new file mode 100644 index 0000000000000..51579a9bfb4e0 --- /dev/null +++ b/src/test/ui/type-ascription/ref-def.rs @@ -0,0 +1,24 @@ +#![feature(type_ascription)] + +struct Foo { + a : u32, +} + +fn main() { + let foo = Foo { a : 1 }; + let r = &mut foo; + + let ref x = r : &Foo; + //~^ ERROR: type ascriptions are not + + let ref another_one = (r : &Foo).a; + //~^ ERROR: type ascriptions are not + + let arr = [4,5,6]; + let arr_ref = &arr; + let ref again = (arr_ref : &[u32])[1]; + //~^ ERROR: type ascriptions are not + + let ref last_one = &*(arr_ref : &[u32]); + //~^ ERROR: type ascriptions are not +} diff --git a/src/test/ui/type-ascription/ref-def.stderr b/src/test/ui/type-ascription/ref-def.stderr new file mode 100644 index 0000000000000..71217dc16d15f --- /dev/null +++ b/src/test/ui/type-ascription/ref-def.stderr @@ -0,0 +1,46 @@ +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/ref-def.rs:11:15 + | +LL | let ref x = r : &Foo; + | ^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/ref-def.rs:14:25 + | +LL | let ref another_one = (r : &Foo).a; + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let r: &Foo = &mut foo; + | ^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/ref-def.rs:19:19 + | +LL | let ref again = (arr_ref : &[u32])[1]; + | ^^^^^^^^^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let arr_ref: &[u32] = &arr; + | ^^^^^^^^^^^^^^^^^^^ + +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/ref-def.rs:22:24 + | +LL | let ref last_one = &*(arr_ref : &[u32]); + | ^^^^^^^^^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable + | +LL | let arr_ref: &[u32] = &arr; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/type/type-ascription-precedence.stderr b/src/test/ui/type/type-ascription-precedence.stderr index 92d3f18e82f44..86333606eeec5 100644 --- a/src/test/ui/type/type-ascription-precedence.stderr +++ b/src/test/ui/type/type-ascription-precedence.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/type-ascription-precedence.rs:31:7 | LL | &(S: &S); - | ^ expected `&S`, found struct `S` + | ^ + | | + | expected `&S`, found struct `S` + | help: consider borrowing here: `&S` error[E0308]: mismatched types --> $DIR/type-ascription-precedence.rs:35:7 diff --git a/src/test/ui/type/type-ascription-soundness.rs b/src/test/ui/type/type-ascription-soundness.rs index d583fc2131a74..5f11427c2e6f4 100644 --- a/src/test/ui/type/type-ascription-soundness.rs +++ b/src/test/ui/type/type-ascription-soundness.rs @@ -4,10 +4,14 @@ fn main() { let arr = &[1u8, 2, 3]; - let ref x = arr: &[u8]; //~ ERROR mismatched types - let ref mut x = arr: &[u8]; //~ ERROR mismatched types - match arr: &[u8] { //~ ERROR mismatched types + let ref x = arr: &[u8]; + //~^ ERROR type ascriptions are not + let ref mut x = arr: &[u8]; + //~^ ERROR type ascriptions are not + match arr: &[u8] { + //~^ ERROR type ascriptions are not ref x => {} } - let _len = (arr: &[u8]).len(); //~ ERROR mismatched types + let _len = (arr: &[u8]).len(); + //~^ ERROR type ascriptions are not } diff --git a/src/test/ui/type/type-ascription-soundness.stderr b/src/test/ui/type/type-ascription-soundness.stderr index 6ed940823af1a..7c6c1a1fa7857 100644 --- a/src/test/ui/type/type-ascription-soundness.stderr +++ b/src/test/ui/type/type-ascription-soundness.stderr @@ -1,39 +1,46 @@ -error[E0308]: mismatched types +error: type ascriptions are not allowed in lvalue contexts --> $DIR/type-ascription-soundness.rs:7:17 | LL | let ref x = arr: &[u8]; - | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | ^^^^^^^^^^ | - = note: expected reference `&[u8]` - found reference `&[u8; 3]` +help: try to use the type ascription when creating the local variable + | +LL | let arr: &[u8] = &[1u8, 2, 3]; + | ^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/type-ascription-soundness.rs:8:21 +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription-soundness.rs:9:21 | LL | let ref mut x = arr: &[u8]; - | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | ^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable | - = note: expected reference `&[u8]` - found reference `&[u8; 3]` +LL | let arr: &[u8] = &[1u8, 2, 3]; + | ^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/type-ascription-soundness.rs:9:11 +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription-soundness.rs:11:11 | LL | match arr: &[u8] { - | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | ^^^^^^^^^^ | - = note: expected reference `&[u8]` - found reference `&[u8; 3]` +help: try to use the type ascription when creating the local variable + | +LL | let arr: &[u8] = &[1u8, 2, 3]; + | ^^^^^^^^^^^^^^ -error[E0308]: mismatched types - --> $DIR/type-ascription-soundness.rs:12:17 +error: type ascriptions are not allowed in lvalue contexts + --> $DIR/type-ascription-soundness.rs:15:16 | LL | let _len = (arr: &[u8]).len(); - | ^^^ expected slice `[u8]`, found array `[u8; 3]` + | ^^^^^^^^^^^^ + | +help: try to use the type ascription when creating the local variable | - = note: expected reference `&[u8]` - found reference `&[u8; 3]` +LL | let arr: &[u8] = &[1u8, 2, 3]; + | ^^^^^^^^^^^^^^ error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`.