Skip to content

Commit

Permalink
Auto merge of #95351 - Dylan-DPC:rollup-o1il7tx, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #91981 (Recover suggestions and useful information lost in previous PR)
 - #93469 (Skip pointing out ambiguous impls in alloc/std crates too in inference errors)
 - #95335 (Move resolve_path to rustc_builtin_macros and make it private)
 - #95340 (interpret: with enforce_number_validity, ensure integers are truly Scalar::Int (i.e., no pointers))
 - #95341 (ARMv6K Horizon OS has_thread_local support)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Mar 27, 2022
2 parents 06c3c62 + 2ab4ad5 commit 185a3f0
Show file tree
Hide file tree
Showing 51 changed files with 281 additions and 149 deletions.
47 changes: 43 additions & 4 deletions compiler/rustc_builtin_macros/src/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_expand::base::{self, *};
use rustc_expand::module::DirOwnership;
use rustc_parse::parser::{ForceCollect, Parser};
use rustc_parse::{self, new_parser_from_file};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
use rustc_span::symbol::Symbol;
use rustc_span::{self, Pos, Span};
use rustc_span::{self, FileName, Pos, Span};

use smallvec::SmallVec;
use std::path::PathBuf;
use std::rc::Rc;

// These macros all relate to the file system; they either return
Expand Down Expand Up @@ -102,7 +104,7 @@ pub fn expand_include<'cx>(
return DummyResult::any(sp);
};
// The file will be added to the code map by the parser
let file = match cx.resolve_path(file, sp) {
let file = match resolve_path(cx, file, sp) {
Ok(f) => f,
Err(mut err) => {
err.emit();
Expand Down Expand Up @@ -171,7 +173,7 @@ pub fn expand_include_str(
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
return DummyResult::any(sp);
};
let file = match cx.resolve_path(file, sp) {
let file = match resolve_path(cx, file, sp) {
Ok(f) => f,
Err(mut err) => {
err.emit();
Expand Down Expand Up @@ -205,7 +207,7 @@ pub fn expand_include_bytes(
let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
return DummyResult::any(sp);
};
let file = match cx.resolve_path(file, sp) {
let file = match resolve_path(cx, file, sp) {
Ok(f) => f,
Err(mut err) => {
err.emit();
Expand All @@ -220,3 +222,40 @@ pub fn expand_include_bytes(
}
}
}

/// Resolves a `path` mentioned inside Rust code, returning an absolute path.
///
/// This unifies the logic used for resolving `include_X!`.
fn resolve_path<'a>(
cx: &mut ExtCtxt<'a>,
path: impl Into<PathBuf>,
span: Span,
) -> PResult<'a, PathBuf> {
let path = path.into();

// Relative paths are resolved relative to the file in which they are found
// after macro expansion (that is, they are unhygienic).
if !path.is_absolute() {
let callsite = span.source_callsite();
let mut result = match cx.source_map().span_to_filename(callsite) {
FileName::Real(name) => name
.into_local_path()
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
return Err(cx.struct_span_err(
span,
&format!(
"cannot resolve relative path in non-file source `{}`",
cx.source_map().filename_for_diagnostics(&other)
),
));
}
};
result.pop();
result.push(path);
Ok(result)
} else {
Ok(path)
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match scalar.try_to_int() {
Ok(int) => int.is_null(),
Err(_) => {
// Can only happen during CTFE.
let ptr = self.scalar_to_ptr(scalar);
match self.memory.ptr_try_get_alloc(ptr) {
Ok((alloc_id, offset, _)) => {
Expand All @@ -455,7 +456,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
offset > size
}
Err(offset) => offset == 0,
Err(_offset) => bug!("a non-int scalar is always a pointer"),
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::hash::Hash;

use super::{
alloc_range, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine,
MemPlaceMeta, OpTy, ScalarMaybeUninit, ValueVisitor,
MemPlaceMeta, OpTy, Scalar, ScalarMaybeUninit, ValueVisitor,
};

macro_rules! throw_validation_failure {
Expand Down Expand Up @@ -521,8 +521,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
if M::enforce_number_validity(self.ecx) {
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok());
// Integers/floats with number validity: Must be scalar bits, pointers are dangerous.
// As a special exception we *do* match on a `Scalar` here, since we truly want
// to know its underlying representation (and *not* cast it to an integer).
let is_bits =
value.check_init().map_or(false, |v| matches!(v, Scalar::Int(..)));
if !is_bits {
throw_validation_failure!(self.path,
{ "{:x}", value } expected { "initialized plain (non-pointer) bytes" }
Expand Down
39 changes: 2 additions & 37 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
use rustc_attr::{self as attr, Deprecation, Stability};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::BuiltinLintDiagnostics;
use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
Expand All @@ -20,7 +20,7 @@ use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};

use std::default::Default;
Expand Down Expand Up @@ -1128,41 +1128,6 @@ impl<'a> ExtCtxt<'a> {
pub fn check_unused_macros(&mut self) {
self.resolver.check_unused_macros();
}

/// Resolves a `path` mentioned inside Rust code, returning an absolute path.
///
/// This unifies the logic used for resolving `include_X!`.
///
/// FIXME: move this to `rustc_builtin_macros` and make it private.
pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PResult<'a, PathBuf> {
let path = path.into();

// Relative paths are resolved relative to the file in which they are found
// after macro expansion (that is, they are unhygienic).
if !path.is_absolute() {
let callsite = span.source_callsite();
let mut result = match self.source_map().span_to_filename(callsite) {
FileName::Real(name) => name
.into_local_path()
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
return Err(self.struct_span_err(
span,
&format!(
"cannot resolve relative path in non-file source `{}`",
self.source_map().filename_for_diagnostics(&other)
),
));
}
};
result.pop();
result.push(path);
Ok(result)
} else {
Ok(path)
}
}
}

/// Extracts a string literal from the macro expanded version of `expr`,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,9 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
)
| (&ty::Infer(ty::InferTy::TyVar(_)), _)
| (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
(&ty::Ref(reg_a, ty_a, mut_a), &ty::Ref(reg_b, ty_b, mut_b)) => {
reg_a == reg_b && mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b)
}
_ => a == b,
}
}
Expand Down Expand Up @@ -602,7 +605,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
match *cause.code() {
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
let ty = self.resolve_vars_if_possible(root_ty);
if ty.is_suggestable() {
if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
{
// don't show type `_`
err.span_label(span, format!("this expression has type `{}`", ty));
}
Expand Down
31 changes: 31 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
value.fold_with(&mut r)
}

pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
if !value.needs_infer() {
return value; // Avoid duplicated subst-folding.
}
let mut r = InferenceLiteralEraser { tcx: self.tcx };
value.fold_with(&mut r)
}

/// Returns the first unresolved variable contained in `T`. In the
/// process of visiting `T`, this will resolve (where possible)
/// type variables in `T`, but it never constructs the final,
Expand Down Expand Up @@ -1785,6 +1796,26 @@ impl<'tcx> TyOrConstInferVar<'tcx> {
}
}

/// Replace `{integer}` with `i32` and `{float}` with `f64`.
/// Used only for diagnostics.
struct InferenceLiteralEraser<'tcx> {
tcx: TyCtxt<'tcx>,
}

impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}

fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.kind() {
ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => self.tcx.types.i32,
ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => self.tcx.types.f64,
_ => ty.super_fold_with(self),
}
}
}

struct ShallowResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub fn target() -> Target {
pre_link_args,
exe_suffix: ".elf".to_string(),
no_default_libraries: false,
has_thread_local: true,
..Default::default()
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1954,7 +1954,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {

if self.is_tainted_by_errors()
&& crate_names.len() == 1
&& crate_names[0] == "`core`"
&& ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
&& spans.len() == 0
{
// Avoid complaining about other inference issues for expressions like
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::{
self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
};
Expand Down Expand Up @@ -83,7 +84,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(param_local_id) = param.def_id.as_local() {
let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id);
let param_name = tcx.hir().ty_param_name(param_hir_id);
let param_type = tcx.type_of(param.def_id);
let param_type = tcx.infer_ctxt().enter(|infcx| {
infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id))
});
if param_type.is_suggestable() {
err.span_suggestion(
tcx.def_span(src_def_id),
Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,20 +521,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
can_suggest: bool,
fn_id: hir::HirId,
) -> bool {
let found =
self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
// Only suggest changing the return type for methods that
// haven't set a return type at all (and aren't `fn main()` or an impl).
match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
(&hir::FnRetTy::DefaultReturn(span), true, true, true) => {
err.span_suggestion(
span,
"try adding a return type",
format!("-> {} ", self.resolve_vars_with_obligations(found)),
format!("-> {} ", found),
Applicability::MachineApplicable,
);
true
}
(&hir::FnRetTy::DefaultReturn(span), false, true, true) => {
err.span_label(span, "possibly return type missing here?");
// FIXME: if `found` could be `impl Iterator` or `impl Fn*`, we should suggest
// that.
err.span_suggestion(
span,
"a return type might be missing here",
"-> _ ".to_string(),
Applicability::HasPlaceholders,
);
true
}
(&hir::FnRetTy::DefaultReturn(span), _, false, true) => {
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/async-await/issue-61076.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ async fn baz() -> Result<(), ()> {

async fn match_() {
match tuple() { //~ HELP consider `await`ing on the `Future`
//~^ NOTE this expression has type `impl Future<Output = Tuple>`
Tuple(_) => {} //~ ERROR mismatched types
//~^ NOTE expected opaque type, found struct `Tuple`
//~| NOTE expected opaque type `impl Future<Output = Tuple>`
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/async-await/issue-61076.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ LL | struct_().await.method();
| ++++++

error[E0308]: mismatched types
--> $DIR/issue-61076.rs:90:9
--> $DIR/issue-61076.rs:91:9
|
LL | match tuple() {
| ------- this expression has type `impl Future<Output = Tuple>`
LL |
LL | Tuple(_) => {}
| ^^^^^^^^ expected opaque type, found struct `Tuple`
|
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/async-await/suggest-missing-await.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ LL ~ 1 => dummy().await,
error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:53:9
|
LL | let _x = match dummy() {
| ------- this expression has type `impl Future<Output = ()>`
LL | () => {}
| ^^ expected opaque type, found `()`
|
Expand All @@ -109,6 +111,9 @@ LL | let _x = match dummy().await {
error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:67:9
|
LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Ok(_) => {}
| ^^^^^ expected opaque type, found enum `Result`
|
Expand All @@ -127,6 +132,9 @@ LL | match dummy_result().await {
error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:69:9
|
LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Err(_) => {}
| ^^^^^^ expected opaque type, found enum `Result`
|
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/blind/blind-item-block-middle.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | mod foo { pub struct bar; }
| --------------- unit struct defined here
...
LL | let bar = 5;
| ^^^
| ^^^ - this expression has type `{integer}`
| |
| expected integer, found struct `bar`
| `bar` is interpreted as a unit struct, not a new binding
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/block-result/issue-20862.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-20862.rs:2:5
|
LL | fn foo(x: i32) {
| - possibly return type missing here?
| - help: a return type might be missing here: `-> _`
LL | |y| x + y
| ^^^^^^^^^ expected `()`, found closure
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/default-match-bindings-forbidden.rs:4:5
|
LL | (x, y) = &(1, 2);
| ^^^^^^ expected reference, found tuple
| ^^^^^^ ------- this expression has type `&({integer}, {integer})`
| |
| expected reference, found tuple
|
= note: expected type `&({integer}, {integer})`
found tuple `(_, _)`
Expand Down
Loading

0 comments on commit 185a3f0

Please sign in to comment.