diff --git a/src/ci/docker/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/dist-x86_64-linux/build-gcc.sh index 7f6e94d326ddf..ddc2066537cef 100755 --- a/src/ci/docker/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/dist-x86_64-linux/build-gcc.sh @@ -32,6 +32,7 @@ hide_output ../gcc-$GCC/configure \ --enable-languages=c,c++ hide_output make -j10 hide_output make install +ln -s gcc /rustroot/bin/cc cd .. rm -rf gcc-build diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index e5d4e1c533c7b..f66ff894ae865 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -28,7 +28,7 @@ // It's cleaner to just turn off the unused_imports warning than to fix them. #![allow(unused_imports)] -use core::borrow::Borrow; +use core::borrow::{Borrow, BorrowMut}; use core::str::pattern::{Pattern, Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::mem; use core::ptr; @@ -190,6 +190,14 @@ impl Borrow for String { } } +#[stable(feature = "string_borrow_mut", since = "1.36.0")] +impl BorrowMut for String { + #[inline] + fn borrow_mut(&mut self) -> &mut str { + &mut self[..] + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ToOwned for str { type Owned = String; diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 1cc6500d0384f..b48d81f2ef8f4 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -144,6 +144,14 @@ impl<'tcx> Arena<'tcx> { } } + #[inline] + pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { + if value.len() == 0 { + return &mut [] + } + self.dropless.alloc_slice(value) + } + pub fn alloc_from_iter< T: ArenaAllocatable, I: IntoIterator diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 8a4594fe0e89e..2592af7d4ad5a 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -369,7 +369,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprKind::AddrOf(_, ref e) | hir::ExprKind::Cast(ref e, _) | hir::ExprKind::Type(ref e, _) | - hir::ExprKind::Use(ref e) | + hir::ExprKind::DropTemps(ref e) | hir::ExprKind::Unary(_, ref e) | hir::ExprKind::Field(ref e, _) | hir::ExprKind::Yield(ref e) | diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3d727f7cd9128..0c73d97394fda 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1029,7 +1029,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(subexpression); visitor.visit_ty(typ) } - ExprKind::Use(ref subexpression) => { + ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } ExprKind::If(ref head_expression, ref if_block, ref optional_else) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index df455a725c5ba..f4209a39c83a7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4671,7 +4671,7 @@ impl<'a> LoweringContext<'a> { // The construct was introduced in #21984. // FIXME(60253): Is this still necessary? // Also, add the attributes to the outer returned expr node. - return self.expr_use(head_sp, match_expr, e.attrs.clone()) + return self.expr_drop_temps(head_sp, match_expr, e.attrs.clone()) } // Desugar `ExprKind::Try` @@ -5030,15 +5030,19 @@ impl<'a> LoweringContext<'a> { ) } - /// Wrap the given `expr` in `hir::ExprKind::Use`. + /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`. /// - /// In terms of drop order, it has the same effect as - /// wrapping `expr` in `{ let _t = $expr; _t }` but - /// should provide better compile-time performance. + /// In terms of drop order, it has the same effect as wrapping `expr` in + /// `{ let _t = $expr; _t }` but should provide better compile-time performance. /// /// The drop order can be important in e.g. `if expr { .. }`. - fn expr_use(&mut self, span: Span, expr: P, attrs: ThinVec) -> hir::Expr { - self.expr(span, hir::ExprKind::Use(expr), attrs) + fn expr_drop_temps( + &mut self, + span: Span, + expr: P, + attrs: ThinVec + ) -> hir::Expr { + self.expr(span, hir::ExprKind::DropTemps(expr), attrs) } fn expr_match( @@ -5400,3 +5404,65 @@ fn body_ids(bodies: &BTreeMap) -> Vec { body_ids.sort_by_key(|b| bodies[b].value.span); body_ids } + +/// Checks if the specified expression is a built-in range literal. +/// (See: `LoweringContext::lower_expr()`). +pub fn is_range_literal(sess: &Session, expr: &hir::Expr) -> bool { + use hir::{Path, QPath, ExprKind, TyKind}; + + // Returns whether the given path represents a (desugared) range, + // either in std or core, i.e. has either a `::std::ops::Range` or + // `::core::ops::Range` prefix. + fn is_range_path(path: &Path) -> bool { + let segs: Vec<_> = path.segments.iter().map(|seg| seg.ident.as_str().to_string()).collect(); + let segs: Vec<_> = segs.iter().map(|seg| &**seg).collect(); + + // "{{root}}" is the equivalent of `::` prefix in `Path`. + if let ["{{root}}", std_core, "ops", range] = segs.as_slice() { + (*std_core == "std" || *std_core == "core") && range.starts_with("Range") + } else { + false + } + }; + + // Check whether a span corresponding to a range expression is a + // range literal, rather than an explicit struct or `new()` call. + fn is_lit(sess: &Session, span: &Span) -> bool { + let source_map = sess.source_map(); + let end_point = source_map.end_point(*span); + + if let Ok(end_string) = source_map.span_to_snippet(end_point) { + !(end_string.ends_with("}") || end_string.ends_with(")")) + } else { + false + } + }; + + match expr.node { + // All built-in range literals but `..=` and `..` desugar to `Struct`s. + ExprKind::Struct(ref qpath, _, _) => { + if let QPath::Resolved(None, ref path) = **qpath { + return is_range_path(&path) && is_lit(sess, &expr.span); + } + } + + // `..` desugars to its struct path. + ExprKind::Path(QPath::Resolved(None, ref path)) => { + return is_range_path(&path) && is_lit(sess, &expr.span); + } + + // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. + ExprKind::Call(ref func, _) => { + if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node { + if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node { + let new_call = segment.ident.as_str() == "new"; + return is_range_path(&path) && is_lit(sess, &expr.span) && new_call; + } + } + } + + _ => {} + } + + false +} diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 8418658ab6878..5a2807ac93d85 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1366,7 +1366,7 @@ impl Expr { ExprKind::Unary(..) => ExprPrecedence::Unary, ExprKind::Lit(_) => ExprPrecedence::Lit, ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast, - ExprKind::Use(ref expr, ..) => expr.precedence(), + ExprKind::DropTemps(ref expr, ..) => expr.precedence(), ExprKind::If(..) => ExprPrecedence::If, ExprKind::While(..) => ExprPrecedence::While, ExprKind::Loop(..) => ExprPrecedence::Loop, @@ -1438,7 +1438,7 @@ impl Expr { ExprKind::Binary(..) | ExprKind::Yield(..) | ExprKind::Cast(..) | - ExprKind::Use(..) | + ExprKind::DropTemps(..) | ExprKind::Err => { false } @@ -1488,10 +1488,12 @@ pub enum ExprKind { Cast(P, P), /// A type reference (e.g., `Foo`). Type(P, P), - /// Semantically equivalent to `{ let _t = expr; _t }`. - /// Maps directly to `hair::ExprKind::Use`. - /// Only exists to tweak the drop order in HIR. - Use(P), + /// Wraps the expression in a terminating scope. + /// This makes it semantically equivalent to `{ let _t = expr; _t }`. + /// + /// This construct only exists to tweak the drop order in HIR lowering. + /// An example of that is the desugaring of `for` loops. + DropTemps(P), /// An `if` block, with an optional else block. /// /// I.e., `if { } else { }`. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 06225364f6c70..54816316f0bf5 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1388,7 +1388,7 @@ impl<'a> State<'a> { self.word_space(":")?; self.print_type(&ty)?; } - hir::ExprKind::Use(ref init) => { + hir::ExprKind::DropTemps(ref init) => { // Print `{`: self.cbox(indent_unit)?; self.ibox(0)?; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 27ebcc55b1e72..3b9af75bd0ab8 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -520,7 +520,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.consume_expr(&base); } - hir::ExprKind::Use(ref expr) => { + hir::ExprKind::DropTemps(ref expr) => { self.consume_expr(&expr); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 966bec8381ae7..2ae53a5df3a86 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -521,7 +521,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Binary(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Cast(..) | - hir::ExprKind::Use(..) | + hir::ExprKind::DropTemps(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(_) | @@ -1222,7 +1222,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::AddrOf(_, ref e) | hir::ExprKind::Cast(ref e, _) | hir::ExprKind::Type(ref e, _) | - hir::ExprKind::Use(ref e) | + hir::ExprKind::DropTemps(ref e) | hir::ExprKind::Unary(_, ref e) | hir::ExprKind::Yield(ref e) | hir::ExprKind::Repeat(ref e, _) => { @@ -1526,7 +1526,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Index(..) | hir::ExprKind::Field(..) | hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) | - hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) | hir::ExprKind::Unary(..) | + hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index d24ee228d538c..34b44234279f2 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -677,7 +677,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) | - hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::Use(..) | + hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) | hir::ExprKind::DropTemps(..) | hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) | hir::ExprKind::Binary(..) | hir::ExprKind::While(..) | hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f9491a1e8f4e6..2b88f273adce4 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -908,8 +908,8 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: visitor.cx.var_parent = visitor.cx.parent; } - hir::ExprKind::Use(ref expr) => { - // `Use(expr)` does not denote a conditional scope. + hir::ExprKind::DropTemps(ref expr) => { + // `DropTemps(expr)` does not denote a conditional scope. // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. terminating(expr.hir_id.local_id); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index eaf9fd1bc7659..b96ef1b7a869b 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -245,13 +245,13 @@ rustc_queries! { /// Get a map with the variance of every item; use `item_variance` /// instead. - query crate_variances(_: CrateNum) -> Lrc { + query crate_variances(_: CrateNum) -> Lrc> { desc { "computing the variances for items in this crate" } } /// Maps from def-id of a type or region parameter to its /// (inferred) variance. - query variances_of(_: DefId) -> Lrc> {} + query variances_of(_: DefId) -> &'tcx [ty::Variance] {} } TypeChecking { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 69532b9b2c4ef..6b938ea2fccdc 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -332,15 +332,11 @@ pub enum Variance { /// `tcx.variances_of()` to get the variance for a *particular* /// item. #[derive(HashStable)] -pub struct CrateVariancesMap { +pub struct CrateVariancesMap<'tcx> { /// For each item with generics, maps to a vector of the variance /// of its generics. If an item has no generics, it will have no /// entry. - pub variances: FxHashMap>>, - - /// An empty vector, useful for cloning. - #[stable_hasher(ignore)] - pub empty_variance: Lrc>, + pub variances: FxHashMap, } impl Variance { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 1f5a39cbef14e..2638a1c7c8808 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -60,7 +60,7 @@ pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized { b_subst); let opt_variances = self.tcx().variances_of(item_def_id); - relate_substs(self, Some(&opt_variances), a_subst, b_subst) + relate_substs(self, Some(opt_variances), a_subst, b_subst) } /// Switch variance for the purpose of relating `a` and `b`. @@ -122,7 +122,7 @@ impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> { } pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&Vec>, + variances: Option<&[ty::Variance]>, a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>) -> RelateResult<'tcx, SubstsRef<'tcx>> diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index d3223c6edb809..f4ebfd79fe1db 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] -use rustc::hir::Node; +use rustc::hir::{ExprKind, Node}; +use rustc::hir::lowering::is_range_literal; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx}; @@ -57,6 +58,347 @@ impl TypeLimits { } } +/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint. +/// Returns `true` iff the lint was overridden. +fn lint_overflowing_range_endpoint<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + lit: &ast::Lit, + lit_val: u128, + max: u128, + expr: &'tcx hir::Expr, + parent_expr: &'tcx hir::Expr, + ty: impl std::fmt::Debug, +) -> bool { + // We only want to handle exclusive (`..`) ranges, + // which are represented as `ExprKind::Struct`. + if let ExprKind::Struct(_, eps, _) = &parent_expr.node { + debug_assert_eq!(eps.len(), 2); + // We can suggest using an inclusive range + // (`..=`) instead only if it is the `end` that is + // overflowing and only by 1. + if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max { + let mut err = cx.struct_span_lint( + OVERFLOWING_LITERALS, + parent_expr.span, + &format!("range endpoint is out of range for `{:?}`", ty), + ); + if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) { + use ast::{LitKind, LitIntType}; + // We need to preserve the literal's suffix, + // as it may determine typing information. + let suffix = match lit.node { + LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s), + LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s), + LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), + _ => bug!(), + }; + let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); + err.span_suggestion( + parent_expr.span, + &"use an inclusive range instead", + suggestion, + Applicability::MachineApplicable, + ); + err.emit(); + return true; + } + } + } + + false +} + +// For `isize` & `usize`, be conservative with the warnings, so that the +// warnings are consistent between 32- and 64-bit platforms. +fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) { + match int_ty { + ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128), + ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128), + ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128), + ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128), + ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128), + ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()), + } +} + +fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) { + match uint_ty { + ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128), + ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128), + ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128), + ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128), + ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128), + ast::UintTy::U128 => (u128::min_value(), u128::max_value()), + } +} + +fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option { + let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?; + let firstch = src.chars().next()?; + + if firstch == '0' { + match src.chars().nth(1) { + Some('x') | Some('b') => return Some(src), + _ => return None, + } + } + + None +} + +fn report_bin_hex_error( + cx: &LateContext<'_, '_>, + expr: &hir::Expr, + ty: attr::IntType, + repr_str: String, + val: u128, + negative: bool, +) { + let size = layout::Integer::from_attr(&cx.tcx, ty).size(); + let (t, actually) = match ty { + attr::IntType::SignedInt(t) => { + let actually = sign_extend(val, size) as i128; + (format!("{:?}", t), actually.to_string()) + } + attr::IntType::UnsignedInt(t) => { + let actually = truncate(val, size); + (format!("{:?}", t), actually.to_string()) + } + }; + let mut err = cx.struct_span_lint( + OVERFLOWING_LITERALS, + expr.span, + &format!("literal out of range for {}", t), + ); + err.note(&format!( + "the literal `{}` (decimal `{}`) does not fit into \ + an `{}` and will become `{}{}`", + repr_str, val, t, actually, t + )); + if let Some(sugg_ty) = + get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) + { + if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { + let (sans_suffix, _) = repr_str.split_at(pos); + err.span_suggestion( + expr.span, + &format!("consider using `{}` instead", sugg_ty), + format!("{}{}", sans_suffix, sugg_ty), + Applicability::MachineApplicable + ); + } else { + err.help(&format!("consider using `{}` instead", sugg_ty)); + } + } + + err.emit(); +} + +// This function finds the next fitting type and generates a suggestion string. +// It searches for fitting types in the following way (`X < Y`): +// - `iX`: if literal fits in `uX` => `uX`, else => `iY` +// - `-iX` => `iY` +// - `uX` => `uY` +// +// No suggestion for: `isize`, `usize`. +fn get_type_suggestion<'a>( + t: Ty<'_>, + val: u128, + negative: bool, +) -> Option { + use syntax::ast::IntTy::*; + use syntax::ast::UintTy::*; + macro_rules! find_fit { + ($ty:expr, $val:expr, $negative:expr, + $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => { + { + let _neg = if negative { 1 } else { 0 }; + match $ty { + $($type => { + $(if !negative && val <= uint_ty_range($utypes).1 { + return Some(format!("{:?}", $utypes)) + })* + $(if val <= int_ty_range($itypes).1 as u128 + _neg { + return Some(format!("{:?}", $itypes)) + })* + None + },)* + _ => None + } + } + } + } + match t.sty { + ty::Int(i) => find_fit!(i, val, negative, + I8 => [U8] => [I16, I32, I64, I128], + I16 => [U16] => [I32, I64, I128], + I32 => [U32] => [I64, I128], + I64 => [U64] => [I128], + I128 => [U128] => []), + ty::Uint(u) => find_fit!(u, val, negative, + U8 => [U8, U16, U32, U64, U128] => [], + U16 => [U16, U32, U64, U128] => [], + U32 => [U32, U64, U128] => [], + U64 => [U64, U128] => [], + U128 => [U128] => []), + _ => None, + } +} + +fn lint_int_literal<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + type_limits: &TypeLimits, + e: &'tcx hir::Expr, + lit: &ast::Lit, + t: ast::IntTy, + v: u128, +) { + let int_type = if let ast::IntTy::Isize = t { + cx.sess().target.isize_ty + } else { + t + }; + + let (_, max) = int_ty_range(int_type); + let max = max as u128; + let negative = type_limits.negated_expr_id == e.hir_id; + + // Detect literal value out of range [min, max] inclusive + // avoiding use of -min to prevent overflow/panic + if (negative && v > max + 1) || (!negative && v > max) { + if let Some(repr_str) = get_bin_hex_repr(cx, lit) { + report_bin_hex_error( + cx, + e, + attr::IntType::SignedInt(t), + repr_str, + v, + negative, + ); + return; + } + + let par_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id); + if let Node::Expr(par_e) = cx.tcx.hir().get_by_hir_id(par_id) { + if let hir::ExprKind::Struct(..) = par_e.node { + if is_range_literal(cx.sess(), par_e) + && lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t) + { + // The overflowing literal lint was overridden. + return; + } + } + } + + cx.span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for `{:?}`", t), + ); + } +} + +fn lint_uint_literal<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + e: &'tcx hir::Expr, + lit: &ast::Lit, + t: ast::UintTy, +) { + let uint_type = if let ast::UintTy::Usize = t { + cx.sess().target.usize_ty + } else { + t + }; + let (min, max) = uint_ty_range(uint_type); + let lit_val: u128 = match lit.node { + // _v is u8, within range by definition + ast::LitKind::Byte(_v) => return, + ast::LitKind::Int(v, _) => v, + _ => bug!(), + }; + if lit_val < min || lit_val > max { + let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id); + if let Node::Expr(par_e) = cx.tcx.hir().get_by_hir_id(parent_id) { + match par_e.node { + hir::ExprKind::Cast(..) => { + if let ty::Char = cx.tables.expr_ty(par_e).sty { + let mut err = cx.struct_span_lint( + OVERFLOWING_LITERALS, + par_e.span, + "only `u8` can be cast into `char`", + ); + err.span_suggestion( + par_e.span, + &"use a `char` literal instead", + format!("'\\u{{{:X}}}'", lit_val), + Applicability::MachineApplicable, + ); + err.emit(); + return; + } + } + hir::ExprKind::Struct(..) + if is_range_literal(cx.sess(), par_e) => { + if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) { + // The overflowing literal lint was overridden. + return; + } + } + _ => {} + } + } + if let Some(repr_str) = get_bin_hex_repr(cx, lit) { + report_bin_hex_error(cx, e, attr::IntType::UnsignedInt(t), repr_str, lit_val, false); + return; + } + cx.span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for `{:?}`", t), + ); + } +} + +fn lint_literal<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + type_limits: &TypeLimits, + e: &'tcx hir::Expr, + lit: &ast::Lit, +) { + match cx.tables.node_type(e.hir_id).sty { + ty::Int(t) => { + match lit.node { + ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | + ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => { + lint_int_literal(cx, type_limits, e, lit, t, v) + } + _ => bug!(), + }; + } + ty::Uint(t) => { + lint_uint_literal(cx, e, lit, t) + } + ty::Float(t) => { + let is_infinite = match lit.node { + ast::LitKind::Float(v, _) | + ast::LitKind::FloatUnsuffixed(v) => { + match t { + ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), + ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), + } + } + _ => bug!(), + }; + if is_infinite == Ok(true) { + cx.span_lint(OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for `{:?}`", t)); + } + } + _ => {} + } +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) { match e.node { @@ -73,118 +415,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { "comparison is useless due to type limits"); } } - hir::ExprKind::Lit(ref lit) => { - match cx.tables.node_type(e.hir_id).sty { - ty::Int(t) => { - match lit.node { - ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | - ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => { - let int_type = if let ast::IntTy::Isize = t { - cx.sess().target.isize_ty - } else { - t - }; - let (_, max) = int_ty_range(int_type); - let max = max as u128; - let negative = self.negated_expr_id == e.hir_id; - - // Detect literal value out of range [min, max] inclusive - // avoiding use of -min to prevent overflow/panic - if (negative && v > max + 1) || (!negative && v > max) { - if let Some(repr_str) = get_bin_hex_repr(cx, lit) { - report_bin_hex_error( - cx, - e, - attr::IntType::SignedInt(t), - repr_str, - v, - negative, - ); - return; - } - cx.span_lint( - OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t), - ); - return; - } - } - _ => bug!(), - }; - } - ty::Uint(t) => { - let uint_type = if let ast::UintTy::Usize = t { - cx.sess().target.usize_ty - } else { - t - }; - let (min, max) = uint_ty_range(uint_type); - let lit_val: u128 = match lit.node { - // _v is u8, within range by definition - ast::LitKind::Byte(_v) => return, - ast::LitKind::Int(v, _) => v, - _ => bug!(), - }; - if lit_val < min || lit_val > max { - let parent_id = cx.tcx.hir().get_parent_node_by_hir_id(e.hir_id); - if let Node::Expr(parent_expr) = cx.tcx.hir().get_by_hir_id(parent_id) { - if let hir::ExprKind::Cast(..) = parent_expr.node { - if let ty::Char = cx.tables.expr_ty(parent_expr).sty { - let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - parent_expr.span, - "only u8 can be cast into char"); - err.span_suggestion( - parent_expr.span, - &"use a char literal instead", - format!("'\\u{{{:X}}}'", lit_val), - Applicability::MachineApplicable - ); - err.emit(); - return - } - } - } - if let Some(repr_str) = get_bin_hex_repr(cx, lit) { - report_bin_hex_error( - cx, - e, - attr::IntType::UnsignedInt(t), - repr_str, - lit_val, - false, - ); - return; - } - cx.span_lint( - OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t), - ); - } - } - ty::Float(t) => { - let is_infinite = match lit.node { - ast::LitKind::Float(v, _) | - ast::LitKind::FloatUnsuffixed(v) => { - match t { - ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), - ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), - } - } - _ => bug!(), - }; - if is_infinite == Ok(true) { - cx.span_lint(OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t)); - } - } - _ => (), - }; - } - _ => (), + hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit), + _ => {} }; fn is_valid(binop: hir::BinOp, v: T, min: T, max: T) -> bool { @@ -209,30 +441,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { }) } - // for isize & usize, be conservative with the warnings, so that the - // warnings are consistent between 32- and 64-bit platforms - fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) { - match int_ty { - ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128), - ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128), - ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128), - ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128), - ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128), - ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()), - } - } - - fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) { - match uint_ty { - ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128), - ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128), - ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128), - ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128), - ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128), - ast::UintTy::U128 => (u128::min_value(), u128::max_value()), - } - } - fn check_limits(cx: &LateContext<'_, '_>, binop: hir::BinOp, l: &hir::Expr, @@ -289,119 +497,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { _ => false, } } - - fn get_bin_hex_repr(cx: &LateContext<'_, '_>, lit: &ast::Lit) -> Option { - let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?; - let firstch = src.chars().next()?; - - if firstch == '0' { - match src.chars().nth(1) { - Some('x') | Some('b') => return Some(src), - _ => return None, - } - } - - None - } - - // This function finds the next fitting type and generates a suggestion string. - // It searches for fitting types in the following way (`X < Y`): - // - `iX`: if literal fits in `uX` => `uX`, else => `iY` - // - `-iX` => `iY` - // - `uX` => `uY` - // - // No suggestion for: `isize`, `usize`. - fn get_type_suggestion<'a>( - t: Ty<'_>, - val: u128, - negative: bool, - ) -> Option { - use syntax::ast::IntTy::*; - use syntax::ast::UintTy::*; - macro_rules! find_fit { - ($ty:expr, $val:expr, $negative:expr, - $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => { - { - let _neg = if negative { 1 } else { 0 }; - match $ty { - $($type => { - $(if !negative && val <= uint_ty_range($utypes).1 { - return Some(format!("{:?}", $utypes)) - })* - $(if val <= int_ty_range($itypes).1 as u128 + _neg { - return Some(format!("{:?}", $itypes)) - })* - None - },)* - _ => None - } - } - } - } - match t.sty { - ty::Int(i) => find_fit!(i, val, negative, - I8 => [U8] => [I16, I32, I64, I128], - I16 => [U16] => [I32, I64, I128], - I32 => [U32] => [I64, I128], - I64 => [U64] => [I128], - I128 => [U128] => []), - ty::Uint(u) => find_fit!(u, val, negative, - U8 => [U8, U16, U32, U64, U128] => [], - U16 => [U16, U32, U64, U128] => [], - U32 => [U32, U64, U128] => [], - U64 => [U64, U128] => [], - U128 => [U128] => []), - _ => None, - } - } - - fn report_bin_hex_error( - cx: &LateContext<'_, '_>, - expr: &hir::Expr, - ty: attr::IntType, - repr_str: String, - val: u128, - negative: bool, - ) { - let size = layout::Integer::from_attr(&cx.tcx, ty).size(); - let (t, actually) = match ty { - attr::IntType::SignedInt(t) => { - let actually = sign_extend(val, size) as i128; - (format!("{:?}", t), actually.to_string()) - } - attr::IntType::UnsignedInt(t) => { - let actually = truncate(val, size); - (format!("{:?}", t), actually.to_string()) - } - }; - let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - expr.span, - &format!("literal out of range for {}", t), - ); - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ - an `{}` and will become `{}{}`", - repr_str, val, t, actually, t - )); - if let Some(sugg_ty) = - get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) - { - if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { - let (sans_suffix, _) = repr_str.split_at(pos); - err.span_suggestion( - expr.span, - &format!("consider using `{}` instead", sugg_ty), - format!("{}{}", sans_suffix, sugg_ty), - Applicability::MachineApplicable - ); - } else { - err.help(&format!("consider using `{}` instead", sugg_ty)); - } - } - - err.emit(); - } } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 53f06baaa9dd7..b3439e4c9708f 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -106,7 +106,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, let _ = cdata; tcx.calculate_dtor(def_id, &mut |_,_| Ok(())) } - variances_of => { Lrc::new(cdata.get_item_variances(def_id.index)) } + variances_of => { tcx.arena.alloc_from_iter(cdata.get_item_variances(def_id.index)) } associated_item_def_ids => { let mut result = vec![]; cdata.each_child_of_item(def_id.index, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index abb30d042ca4c..00e81ee049183 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -674,8 +674,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { borrow_region: RegionVid, outlived_region: RegionVid, ) -> (ConstraintCategory, bool, Span, Option) { - let (category, from_closure, span) = - self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region); + let (category, from_closure, span) = self.best_blame_constraint( + mir, + borrow_region, + |r| self.provides_universal_region(r, borrow_region, outlived_region) + ); let outlived_fr_name = self.give_region_a_name(infcx, mir, upvars, mir_def_id, outlived_region, &mut 1); (category, from_closure, span, outlived_fr_name) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index ada8e208ec7e6..6e11f1dae9b06 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -759,7 +759,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } } - hir::ExprKind::Use(ref source) => { + hir::ExprKind::DropTemps(ref source) => { ExprKind::Use { source: source.to_ref() } } hir::ExprKind::Box(ref value) => { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index ce54035fe67db..881f63e994d59 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -437,7 +437,7 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::AddrOf(_, ref expr) | hir::ExprKind::Repeat(ref expr, _) | hir::ExprKind::Type(ref expr, _) | - hir::ExprKind::Use(ref expr) => { + hir::ExprKind::DropTemps(ref expr) => { v.check_expr(&expr) } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 689996ccb25a9..8ae66a96c763a 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -7,7 +7,7 @@ use syntax_pos::Span; use rustc::hir; use rustc::hir::def::Def; use rustc::hir::Node; -use rustc::hir::print; +use rustc::hir::{print, lowering::is_range_literal}; use rustc::ty::{self, Ty, AssociatedItem}; use rustc::ty::adjustment::AllowTwoPhase; use errors::{Applicability, DiagnosticBuilder}; @@ -380,7 +380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, // parenthesize borrows of range literals (Issue #54505) - _ if self.is_range_literal(expr) => true, + _ if is_range_literal(self.tcx.sess, expr) => true, _ => false, }; let sugg_expr = if needs_parens { @@ -479,70 +479,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } - /// This function checks if the specified expression is a built-in range literal. - /// (See: `LoweringContext::lower_expr()` in `src/librustc/hir/lowering.rs`). - fn is_range_literal(&self, expr: &hir::Expr) -> bool { - use hir::{Path, QPath, ExprKind, TyKind}; - - // We support `::std::ops::Range` and `::core::ops::Range` prefixes - let is_range_path = |path: &Path| { - let mut segs = path.segments.iter() - .map(|seg| seg.ident.as_str()); - - if let (Some(root), Some(std_core), Some(ops), Some(range), None) = - (segs.next(), segs.next(), segs.next(), segs.next(), segs.next()) - { - // "{{root}}" is the equivalent of `::` prefix in Path - root == "{{root}}" && (std_core == "std" || std_core == "core") - && ops == "ops" && range.starts_with("Range") - } else { - false - } - }; - - let span_is_range_literal = |span: &Span| { - // Check whether a span corresponding to a range expression - // is a range literal, rather than an explicit struct or `new()` call. - let source_map = self.tcx.sess.source_map(); - let end_point = source_map.end_point(*span); - - if let Ok(end_string) = source_map.span_to_snippet(end_point) { - !(end_string.ends_with("}") || end_string.ends_with(")")) - } else { - false - } - }; - - match expr.node { - // All built-in range literals but `..=` and `..` desugar to Structs - ExprKind::Struct(ref qpath, _, _) => { - if let QPath::Resolved(None, ref path) = **qpath { - return is_range_path(&path) && span_is_range_literal(&expr.span); - } - } - // `..` desugars to its struct path - ExprKind::Path(QPath::Resolved(None, ref path)) => { - return is_range_path(&path) && span_is_range_literal(&expr.span); - } - - // `..=` desugars into `::std::ops::RangeInclusive::new(...)` - ExprKind::Call(ref func, _) => { - if let ExprKind::Path(QPath::TypeRelative(ref ty, ref segment)) = func.node { - if let TyKind::Path(QPath::Resolved(None, ref path)) = ty.node { - let call_to_new = segment.ident.as_str() == "new"; - - return is_range_path(&path) && span_is_range_literal(&expr.span) - && call_to_new; - } - } - } - - _ => {} - } - - false - } - pub fn check_for_cast( &self, err: &mut DiagnosticBuilder<'tcx>, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 452bc74bdd051..d2d486b52b3f8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4538,7 +4538,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_expr_eq_type(&e, ty); ty } - ExprKind::Use(ref e) => { + ExprKind::DropTemps(ref e) => { self.check_expr_with_expectation(e, expected) } ExprKind::Array(ref args) => { diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c3b08569d2f1f..1be0248727d01 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -223,19 +223,22 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( let fields = &def_a.non_enum_variant().fields; let coerced_fields = fields.iter().filter_map(|field| { - if tcx.type_of(field.did).is_phantom_data() { - // ignore PhantomData fields - return None - } - let ty_a = field.ty(tcx, substs_a); let ty_b = field.ty(tcx, substs_b); + + if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) { + if layout.is_zst() && layout.details.align.abi.bytes() == 1 { + // ignore ZST fields with alignment of 1 byte + return None; + } + } + if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) { if ok.obligations.is_empty() { create_err( "the trait `DispatchFromDyn` may only be implemented \ for structs containing the field being coerced, \ - `PhantomData` fields, and nothing else" + ZST fields with 1 byte alignment, and nothing else" ).note( &format!( "extra field `{}` of type `{}` is not allowed", diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index 9b9a6bace96b1..88ee1d79f5435 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -36,7 +36,7 @@ pub fn provide(providers: &mut Providers<'_>) { } fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) - -> Lrc { + -> Lrc> { assert_eq!(crate_num, LOCAL_CRATE); let mut arena = arena::TypedArena::default(); let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena); @@ -45,7 +45,7 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) } fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) - -> Lrc> { + -> &'tcx [ty::Variance] { let id = tcx.hir().as_local_hir_id(item_def_id).expect("expected local def-id"); let unsupported = || { // Variance not relevant. @@ -88,6 +88,6 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) let crate_map = tcx.crate_variances(LOCAL_CRATE); crate_map.variances.get(&item_def_id) - .unwrap_or(&crate_map.empty_variance) - .clone() + .map(|p| *p) + .unwrap_or(&[]) } diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 51a1d088ddccb..8edf3c52ccc22 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -8,7 +8,6 @@ use rustc::hir::def_id::DefId; use rustc::ty; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lrc; use super::constraints::*; use super::terms::*; @@ -23,7 +22,9 @@ struct SolveContext<'a, 'tcx: 'a> { solutions: Vec, } -pub fn solve_constraints(constraints_cx: ConstraintContext<'_, '_>) -> ty::CrateVariancesMap { +pub fn solve_constraints<'tcx>( + constraints_cx: ConstraintContext<'_, 'tcx> +) -> ty::CrateVariancesMap<'tcx> { let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; @@ -41,9 +42,8 @@ pub fn solve_constraints(constraints_cx: ConstraintContext<'_, '_>) -> ty::Crate }; solutions_cx.solve(); let variances = solutions_cx.create_map(); - let empty_variance = Lrc::new(Vec::new()); - ty::CrateVariancesMap { variances, empty_variance } + ty::CrateVariancesMap { variances } } impl<'a, 'tcx> SolveContext<'a, 'tcx> { @@ -78,7 +78,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } } - fn enforce_const_invariance(&self, generics: &ty::Generics, variances: &mut Vec) { + fn enforce_const_invariance(&self, generics: &ty::Generics, variances: &mut [ty::Variance]) { let tcx = self.terms_cx.tcx; // Make all const parameters invariant. @@ -94,7 +94,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { } } - fn create_map(&self) -> FxHashMap>> { + fn create_map(&self) -> FxHashMap { let tcx = self.terms_cx.tcx; let solutions = &self.solutions; @@ -103,22 +103,21 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let generics = tcx.generics_of(def_id); let count = generics.count(); - let mut variances = solutions[start..(start + count)].to_vec(); - debug!("id={} variances={:?}", id, variances); + let variances = tcx.arena.alloc_slice(&solutions[start..(start + count)]); // Const parameters are always invariant. - self.enforce_const_invariance(generics, &mut variances); + self.enforce_const_invariance(generics, variances); // Functions are permitted to have unused generic parameters: make those invariant. if let ty::FnDef(..) = tcx.type_of(def_id).sty { - for variance in &mut variances { + for variance in variances.iter_mut() { if *variance == ty::Bivariant { *variance = ty::Invariant; } } } - (def_id, Lrc::new(variances)) + (def_id, &*variances) }).collect() } diff --git a/src/test/run-pass/dispatch_from_dyn_zst.rs b/src/test/run-pass/dispatch_from_dyn_zst.rs new file mode 100644 index 0000000000000..a2181336e00f5 --- /dev/null +++ b/src/test/run-pass/dispatch_from_dyn_zst.rs @@ -0,0 +1,49 @@ +#![feature(unsize, dispatch_from_dyn, never_type)] + +#![allow(dead_code)] + +use std::{ + ops::DispatchFromDyn, + marker::{Unsize, PhantomData}, +}; + +struct Zst; +struct NestedZst(PhantomData<()>, Zst); + + +struct WithUnit(Box, ()); +impl DispatchFromDyn> for WithUnit + where T: Unsize {} + +struct WithPhantom(Box, PhantomData<()>); +impl DispatchFromDyn> for WithPhantom + where T: Unsize {} + +struct WithNever(Box, !); +impl DispatchFromDyn> for WithNever + where T: Unsize {} + +struct WithZst(Box, Zst); +impl DispatchFromDyn> for WithZst + where T: Unsize {} + +struct WithNestedZst(Box, NestedZst); +impl DispatchFromDyn> for WithNestedZst + where T: Unsize {} + + +struct Generic(Box, A); +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn>> + for Generic> + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} + + +fn main() {} diff --git a/src/test/ui/cast_char.rs b/src/test/ui/cast_char.rs index 8c319af9c96e7..9634ed56f7b72 100644 --- a/src/test/ui/cast_char.rs +++ b/src/test/ui/cast_char.rs @@ -2,9 +2,9 @@ fn main() { const XYZ: char = 0x1F888 as char; - //~^ ERROR only u8 can be cast into char + //~^ ERROR only `u8` can be cast into `char` const XY: char = 129160 as char; - //~^ ERROR only u8 can be cast into char + //~^ ERROR only `u8` can be cast into `char` const ZYX: char = '\u{01F888}'; println!("{}", XYZ); } diff --git a/src/test/ui/cast_char.stderr b/src/test/ui/cast_char.stderr index f0c9b8988903b..37ef98bcb5067 100644 --- a/src/test/ui/cast_char.stderr +++ b/src/test/ui/cast_char.stderr @@ -1,8 +1,8 @@ -error: only u8 can be cast into char +error: only `u8` can be cast into `char` --> $DIR/cast_char.rs:4:23 | LL | const XYZ: char = 0x1F888 as char; - | ^^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'` + | ^^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'` | note: lint level defined here --> $DIR/cast_char.rs:1:9 @@ -10,11 +10,11 @@ note: lint level defined here LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -error: only u8 can be cast into char +error: only `u8` can be cast into `char` --> $DIR/cast_char.rs:6:22 | LL | const XY: char = 129160 as char; - | ^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'` + | ^^^^^^^^^^^^^^ help: use a `char` literal instead: `'\u{1F888}'` error: aborting due to 2 previous errors diff --git a/src/test/ui/enum/enum-discrim-too-small2.rs b/src/test/ui/enum/enum-discrim-too-small2.rs index af60564302599..85cd73d6f0855 100644 --- a/src/test/ui/enum/enum-discrim-too-small2.rs +++ b/src/test/ui/enum/enum-discrim-too-small2.rs @@ -5,28 +5,28 @@ enum Ei8 { Ai8 = 23, Bi8 = -23, - Ci8 = 223, //~ ERROR literal out of range for i8 + Ci8 = 223, //~ ERROR literal out of range for `i8` } #[repr(i16)] enum Ei16 { Ai16 = 23, Bi16 = -22333, - Ci16 = 55555, //~ ERROR literal out of range for i16 + Ci16 = 55555, //~ ERROR literal out of range for `i16` } #[repr(i32)] enum Ei32 { Ai32 = 23, Bi32 = -2_000_000_000, - Ci32 = 3_000_000_000, //~ ERROR literal out of range for i32 + Ci32 = 3_000_000_000, //~ ERROR literal out of range for `i32` } #[repr(i64)] enum Ei64 { Ai64 = 23, Bi64 = -9223372036854775808, - Ci64 = 9223372036854775809, //~ ERROR literal out of range for i64 + Ci64 = 9223372036854775809, //~ ERROR literal out of range for `i64` } // u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`. This is a diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr index 6340f5a856ed3..f7220044ba42d 100644 --- a/src/test/ui/enum/enum-discrim-too-small2.stderr +++ b/src/test/ui/enum/enum-discrim-too-small2.stderr @@ -1,4 +1,4 @@ -error: literal out of range for i8 +error: literal out of range for `i8` --> $DIR/enum-discrim-too-small2.rs:8:11 | LL | Ci8 = 223, @@ -10,19 +10,19 @@ note: lint level defined here LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -error: literal out of range for i16 +error: literal out of range for `i16` --> $DIR/enum-discrim-too-small2.rs:15:12 | LL | Ci16 = 55555, | ^^^^^ -error: literal out of range for i32 +error: literal out of range for `i32` --> $DIR/enum-discrim-too-small2.rs:22:12 | LL | Ci32 = 3_000_000_000, | ^^^^^^^^^^^^^ -error: literal out of range for i64 +error: literal out of range for `i64` --> $DIR/enum-discrim-too-small2.rs:29:12 | LL | Ci64 = 9223372036854775809, diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs index c4716893fbc54..b7bc766fbe020 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.rs +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.rs @@ -39,4 +39,13 @@ where T: Unsize, {} //~^^^ ERROR [E0378] +#[repr(align(64))] +struct OverAlignedZst; +struct OverAligned(Box, OverAlignedZst); + +impl DispatchFromDyn> for OverAligned + where + T: Unsize, +{} //~^^^ ERROR [E0378] + fn main() {} diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr index bd016466300d7..6d62d4fd0711d 100644 --- a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr @@ -1,4 +1,4 @@ -error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 | LL | / impl DispatchFromDyn> for WrapperWithExtraField @@ -36,6 +36,17 @@ LL | | T: Unsize, LL | | {} | |__^ -error: aborting due to 4 previous errors +error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else + --> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1 + | +LL | / impl DispatchFromDyn> for OverAligned +LL | | where +LL | | T: Unsize, +LL | | {} + | |__^ + | + = note: extra field `1` of type `OverAlignedZst` is not allowed + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0378`. diff --git a/src/test/ui/lint/deny-overflowing-literals.rs b/src/test/ui/lint/deny-overflowing-literals.rs index ebd6654d39b1f..b887f66e94bd6 100644 --- a/src/test/ui/lint/deny-overflowing-literals.rs +++ b/src/test/ui/lint/deny-overflowing-literals.rs @@ -1,4 +1,4 @@ fn main() { let x: u8 = 256; - //~^ error: literal out of range for u8 + //~^ error: literal out of range for `u8` } diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr index 7313dd0bfb5a7..1263a7bb7fd1b 100644 --- a/src/test/ui/lint/deny-overflowing-literals.stderr +++ b/src/test/ui/lint/deny-overflowing-literals.stderr @@ -1,4 +1,4 @@ -error: literal out of range for u8 +error: literal out of range for `u8` --> $DIR/deny-overflowing-literals.rs:2:17 | LL | let x: u8 = 256; diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.rs b/src/test/ui/lint/lint-range-endpoint-overflow.rs new file mode 100644 index 0000000000000..7034d56aa5d83 --- /dev/null +++ b/src/test/ui/lint/lint-range-endpoint-overflow.rs @@ -0,0 +1,17 @@ +#![deny(overflowing_literals)] + +fn main() { + let range_a = 0..256; //~ ERROR range endpoint is out of range for `u8` + let range_b = 0..=255; // ok + let range_c = 0..=256; //~ ERROR literal out of range for `u8` + let range_d = 256..5; //~ ERROR literal out of range for `u8` + let range_e = 0..257; //~ ERROR literal out of range for `u8` + let _range_f = 0..256u8; //~ ERROR range endpoint is out of range for `u8` + let _range_g = 0..128i8; //~ ERROR range endpoint is out of range for `i8` + + range_a.collect::>(); + range_b.collect::>(); + range_c.collect::>(); + range_d.collect::>(); + range_e.collect::>(); +} diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.stderr b/src/test/ui/lint/lint-range-endpoint-overflow.stderr new file mode 100644 index 0000000000000..939451d6bc022 --- /dev/null +++ b/src/test/ui/lint/lint-range-endpoint-overflow.stderr @@ -0,0 +1,44 @@ +error: range endpoint is out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:4:19 + | +LL | let range_a = 0..256; + | ^^^^^^ help: use an inclusive range instead: `0..=255` + | +note: lint level defined here + --> $DIR/lint-range-endpoint-overflow.rs:1:9 + | +LL | #![deny(overflowing_literals)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:6:23 + | +LL | let range_c = 0..=256; + | ^^^ + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:7:19 + | +LL | let range_d = 256..5; + | ^^^ + +error: literal out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:8:22 + | +LL | let range_e = 0..257; + | ^^^ + +error: range endpoint is out of range for `u8` + --> $DIR/lint-range-endpoint-overflow.rs:9:20 + | +LL | let _range_f = 0..256u8; + | ^^^^^^^^ help: use an inclusive range instead: `0..=255u8` + +error: range endpoint is out of range for `i8` + --> $DIR/lint-range-endpoint-overflow.rs:10:20 + | +LL | let _range_g = 0..128i8; + | ^^^^^^^^ help: use an inclusive range instead: `0..=127i8` + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/lint/lint-type-limits2.rs b/src/test/ui/lint/lint-type-limits2.rs index c4486e0676887..3f90119cd8954 100644 --- a/src/test/ui/lint/lint-type-limits2.rs +++ b/src/test/ui/lint/lint-type-limits2.rs @@ -11,5 +11,5 @@ fn bar() -> i8 { fn baz() -> bool { 128 > bar() //~ ERROR comparison is useless due to type limits - //~| WARN literal out of range for i8 + //~| WARN literal out of range for `i8` } diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr index e7bc407422a12..0b3d292856707 100644 --- a/src/test/ui/lint/lint-type-limits2.stderr +++ b/src/test/ui/lint/lint-type-limits2.stderr @@ -6,7 +6,7 @@ LL | 128 > bar() | = note: requested on the command line with `-D unused-comparisons` -warning: literal out of range for i8 +warning: literal out of range for `i8` --> $DIR/lint-type-limits2.rs:13:5 | LL | 128 > bar() diff --git a/src/test/ui/lint/lint-type-limits3.rs b/src/test/ui/lint/lint-type-limits3.rs index a715c69f7849e..ceecf9ab30bb8 100644 --- a/src/test/ui/lint/lint-type-limits3.rs +++ b/src/test/ui/lint/lint-type-limits3.rs @@ -7,7 +7,7 @@ fn main() { } fn qux() { let mut i = 1i8; while 200 != i { //~ ERROR comparison is useless due to type limits - //~| WARN literal out of range for i8 + //~| WARN literal out of range for `i8` i += 1; } } diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr index 742b6695c24f2..70cd9c859ecf3 100644 --- a/src/test/ui/lint/lint-type-limits3.stderr +++ b/src/test/ui/lint/lint-type-limits3.stderr @@ -6,7 +6,7 @@ LL | while 200 != i { | = note: requested on the command line with `-D unused-comparisons` -warning: literal out of range for i8 +warning: literal out of range for `i8` --> $DIR/lint-type-limits3.rs:9:11 | LL | while 200 != i { diff --git a/src/test/ui/lint/lint-type-overflow.rs b/src/test/ui/lint/lint-type-overflow.rs index 847cdf31dc788..9672da6d3586c 100644 --- a/src/test/ui/lint/lint-type-overflow.rs +++ b/src/test/ui/lint/lint-type-overflow.rs @@ -1,5 +1,3 @@ -// - #![deny(overflowing_literals)] fn test(x: i8) { @@ -9,39 +7,39 @@ fn test(x: i8) { #[allow(unused_variables)] fn main() { let x1: u8 = 255; // should be OK - let x1: u8 = 256; //~ error: literal out of range for u8 + let x1: u8 = 256; //~ error: literal out of range for `u8` let x1 = 255_u8; // should be OK - let x1 = 256_u8; //~ error: literal out of range for u8 + let x1 = 256_u8; //~ error: literal out of range for `u8` let x2: i8 = -128; // should be OK - let x1: i8 = 128; //~ error: literal out of range for i8 + let x1: i8 = 128; //~ error: literal out of range for `i8` - let x3: i8 = -129; //~ error: literal out of range for i8 - let x3: i8 = -(129); //~ error: literal out of range for i8 - let x3: i8 = -{129}; //~ error: literal out of range for i8 + let x3: i8 = -129; //~ error: literal out of range for `i8` + let x3: i8 = -(129); //~ error: literal out of range for `i8` + let x3: i8 = -{129}; //~ error: literal out of range for `i8` - test(1000); //~ error: literal out of range for i8 + test(1000); //~ error: literal out of range for `i8` - let x = 128_i8; //~ error: literal out of range for i8 + let x = 128_i8; //~ error: literal out of range for `i8` let x = 127_i8; let x = -128_i8; let x = -(128_i8); - let x = -129_i8; //~ error: literal out of range for i8 + let x = -129_i8; //~ error: literal out of range for `i8` let x: i32 = 2147483647; // should be OK let x = 2147483647_i32; // should be OK - let x: i32 = 2147483648; //~ error: literal out of range for i32 - let x = 2147483648_i32; //~ error: literal out of range for i32 + let x: i32 = 2147483648; //~ error: literal out of range for `i32` + let x = 2147483648_i32; //~ error: literal out of range for `i32` let x: i32 = -2147483648; // should be OK let x = -2147483648_i32; // should be OK - let x: i32 = -2147483649; //~ error: literal out of range for i32 - let x = -2147483649_i32; //~ error: literal out of range for i32 - let x = 2147483648; //~ error: literal out of range for i32 + let x: i32 = -2147483649; //~ error: literal out of range for `i32` + let x = -2147483649_i32; //~ error: literal out of range for `i32` + let x = 2147483648; //~ error: literal out of range for `i32` - let x = 9223372036854775808_i64; //~ error: literal out of range for i64 + let x = 9223372036854775808_i64; //~ error: literal out of range for `i64` let x = -9223372036854775808_i64; // should be OK - let x = 18446744073709551615_i64; //~ error: literal out of range for i64 - let x: i64 = -9223372036854775809; //~ error: literal out of range for i64 - let x = -9223372036854775809_i64; //~ error: literal out of range for i64 + let x = 18446744073709551615_i64; //~ error: literal out of range for `i64` + let x: i64 = -9223372036854775809; //~ error: literal out of range for `i64` + let x = -9223372036854775809_i64; //~ error: literal out of range for `i64` } diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr index 9da007457aa83..6fcd9b58b2dc7 100644 --- a/src/test/ui/lint/lint-type-overflow.stderr +++ b/src/test/ui/lint/lint-type-overflow.stderr @@ -1,113 +1,113 @@ -error: literal out of range for u8 - --> $DIR/lint-type-overflow.rs:12:18 +error: literal out of range for `u8` + --> $DIR/lint-type-overflow.rs:10:18 | LL | let x1: u8 = 256; | ^^^ | note: lint level defined here - --> $DIR/lint-type-overflow.rs:3:9 + --> $DIR/lint-type-overflow.rs:1:9 | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -error: literal out of range for u8 - --> $DIR/lint-type-overflow.rs:15:14 +error: literal out of range for `u8` + --> $DIR/lint-type-overflow.rs:13:14 | LL | let x1 = 256_u8; | ^^^^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:18:18 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:16:18 | LL | let x1: i8 = 128; | ^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:20:19 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:18:19 | LL | let x3: i8 = -129; | ^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:21:19 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:19:19 | LL | let x3: i8 = -(129); | ^^^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:22:20 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:20:20 | LL | let x3: i8 = -{129}; | ^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:24:10 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:22:10 | LL | test(1000); | ^^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:26:13 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:24:13 | LL | let x = 128_i8; | ^^^^^^ -error: literal out of range for i8 - --> $DIR/lint-type-overflow.rs:30:14 +error: literal out of range for `i8` + --> $DIR/lint-type-overflow.rs:28:14 | LL | let x = -129_i8; | ^^^^^^ -error: literal out of range for i32 - --> $DIR/lint-type-overflow.rs:34:18 +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:32:18 | LL | let x: i32 = 2147483648; | ^^^^^^^^^^ -error: literal out of range for i32 - --> $DIR/lint-type-overflow.rs:35:13 +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:33:13 | LL | let x = 2147483648_i32; | ^^^^^^^^^^^^^^ -error: literal out of range for i32 - --> $DIR/lint-type-overflow.rs:38:19 +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:36:19 | LL | let x: i32 = -2147483649; | ^^^^^^^^^^ -error: literal out of range for i32 - --> $DIR/lint-type-overflow.rs:39:14 +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:37:14 | LL | let x = -2147483649_i32; | ^^^^^^^^^^^^^^ -error: literal out of range for i32 - --> $DIR/lint-type-overflow.rs:40:13 +error: literal out of range for `i32` + --> $DIR/lint-type-overflow.rs:38:13 | LL | let x = 2147483648; | ^^^^^^^^^^ -error: literal out of range for i64 - --> $DIR/lint-type-overflow.rs:42:13 +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:40:13 | LL | let x = 9223372036854775808_i64; | ^^^^^^^^^^^^^^^^^^^^^^^ -error: literal out of range for i64 - --> $DIR/lint-type-overflow.rs:44:13 +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:42:13 | LL | let x = 18446744073709551615_i64; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: literal out of range for i64 - --> $DIR/lint-type-overflow.rs:45:19 +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:43:19 | LL | let x: i64 = -9223372036854775809; | ^^^^^^^^^^^^^^^^^^^ -error: literal out of range for i64 - --> $DIR/lint-type-overflow.rs:46:14 +error: literal out of range for `i64` + --> $DIR/lint-type-overflow.rs:44:14 | LL | let x = -9223372036854775809_i64; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr index 5255f6c75934d..c76e9e25d5a93 100644 --- a/src/test/ui/lint/lint-type-overflow2.stderr +++ b/src/test/ui/lint/lint-type-overflow2.stderr @@ -1,4 +1,4 @@ -warning: literal out of range for i8 +warning: literal out of range for `i8` --> $DIR/lint-type-overflow2.rs:9:20 | LL | let x2: i8 = --128; @@ -10,25 +10,25 @@ note: lint level defined here LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -warning: literal out of range for f32 +warning: literal out of range for `f32` --> $DIR/lint-type-overflow2.rs:11:14 | LL | let x = -3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ -warning: literal out of range for f32 +warning: literal out of range for `f32` --> $DIR/lint-type-overflow2.rs:12:14 | LL | let x = 3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ -warning: literal out of range for f64 +warning: literal out of range for `f64` --> $DIR/lint-type-overflow2.rs:13:14 | LL | let x = -1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: literal out of range for f64 +warning: literal out of range for `f64` --> $DIR/lint-type-overflow2.rs:14:14 | LL | let x = 1.7976931348623159e+308_f64; diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index 5235c9851b53f..dabfb876fbb92 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -1,4 +1,4 @@ -warning: literal out of range for i8 +warning: literal out of range for `i8` --> $DIR/type-overflow.rs:5:17 | LL | let error = 255i8; diff --git a/src/test/ui/nll/local-outlives-static-via-hrtb.rs b/src/test/ui/nll/local-outlives-static-via-hrtb.rs new file mode 100644 index 0000000000000..5f1f9b3a7f229 --- /dev/null +++ b/src/test/ui/nll/local-outlives-static-via-hrtb.rs @@ -0,0 +1,26 @@ +// Test that we handle the case when a local variable is borrowed for `'static` +// due to an outlives constraint involving a region in an incompatible universe + +pub trait Outlives<'this> {} + +impl<'this, T> Outlives<'this> for T where T: 'this {} +trait Reference { + type AssociatedType; +} + +impl<'a, T: 'a> Reference for &'a T { + type AssociatedType = &'a (); +} + +fn assert_static_via_hrtb(_: G) where for<'a> G: Outlives<'a> {} + +fn assert_static_via_hrtb_with_assoc_type(_: &'_ T) +where + for<'a> &'a T: Reference, +{} + +fn main() { + let local = 0; + assert_static_via_hrtb(&local); //~ ERROR `local` does not live long enough + assert_static_via_hrtb_with_assoc_type(&&local); //~ ERROR `local` does not live long enough +} diff --git a/src/test/ui/nll/local-outlives-static-via-hrtb.stderr b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr new file mode 100644 index 0000000000000..61009da49ffed --- /dev/null +++ b/src/test/ui/nll/local-outlives-static-via-hrtb.stderr @@ -0,0 +1,26 @@ +error[E0597]: `local` does not live long enough + --> $DIR/local-outlives-static-via-hrtb.rs:24:28 + | +LL | assert_static_via_hrtb(&local); + | -----------------------^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `local` is borrowed for `'static` +LL | assert_static_via_hrtb_with_assoc_type(&&local); +LL | } + | - `local` dropped here while still borrowed + +error[E0597]: `local` does not live long enough + --> $DIR/local-outlives-static-via-hrtb.rs:25:45 + | +LL | assert_static_via_hrtb_with_assoc_type(&&local); + | ----------------------------------------^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `local` is borrowed for `'static` +LL | } + | - `local` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`.