Skip to content

Commit

Permalink
Auto merge of rust-lang#72251 - Dylan-DPC:rollup-4mik3o7, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - rust-lang#71662 (Implement FromStr for OsString)
 - rust-lang#71677 (Add explicit references to the BuildHasher trait)
 - rust-lang#71724 (Doc alias improvements)
 - rust-lang#71948 (Suggest to await future before ? operator)
 - rust-lang#72090 (rustc_driver: factor out computing the exit code)
 - rust-lang#72206 (Cleanup stale 'FIXME(rust-lang#64197)')
 - rust-lang#72218 (make sure even unleashed miri does not do pointer stuff)
 - rust-lang#72220 ([const-prop] Don't replace Rvalues that are already constants)
 - rust-lang#72224 (doc: add links to rotate_(left|right))

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 16, 2020
2 parents ed084b0 + a27b1b6 commit 163445a
Show file tree
Hide file tree
Showing 37 changed files with 946 additions and 210 deletions.
16 changes: 8 additions & 8 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,8 +1499,8 @@ any high-order bits of `rhs` that would cause the shift to exceed the bitwidth o
Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to
the range of the type, rather than the bits shifted out of the LHS being returned to the other end.
The primitive integer types all implement a `rotate_left` function, which may be what you want
instead.
The primitive integer types all implement a `[`rotate_left`](#method.rotate_left) function,
which may be what you want instead.
# Examples
Expand Down Expand Up @@ -1531,8 +1531,8 @@ removes any high-order bits of `rhs` that would cause the shift to exceed the bi
Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted
to the range of the type, rather than the bits shifted out of the LHS being returned to the other
end. The primitive integer types all implement a `rotate_right` function, which may be what you want
instead.
end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function,
which may be what you want instead.
# Examples
Expand Down Expand Up @@ -3610,8 +3610,8 @@ Note that this is *not* the same as a rotate-left; the
RHS of a wrapping shift-left is restricted to the range
of the type, rather than the bits shifted out of the LHS
being returned to the other end. The primitive integer
types all implement a `rotate_left` function, which may
be what you want instead.
types all implement a [`rotate_left`](#method.rotate_left) function,
which may be what you want instead.
# Examples
Expand Down Expand Up @@ -3644,8 +3644,8 @@ Note that this is *not* the same as a rotate-right; the
RHS of a wrapping shift-right is restricted to the range
of the type, rather than the bits shifted out of the LHS
being returned to the other end. The primitive integer
types all implement a `rotate_right` function, which may
be what you want instead.
types all implement a [`rotate_right`](#method.rotate_right) function,
which may be what you want instead.
# Examples
Expand Down
23 changes: 14 additions & 9 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,16 @@ pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported>
})
}

/// Variant of `catch_fatal_errors` for the `interface::Result` return type
/// that also computes the exit code.
pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
let result = catch_fatal_errors(f).and_then(|result| result);
match result {
Ok(()) => EXIT_SUCCESS,
Err(_) => EXIT_FAILURE,
}
}

lazy_static! {
static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = {
let hook = panic::take_hook();
Expand Down Expand Up @@ -1228,12 +1238,12 @@ pub fn init_rustc_env_logger() {
env_logger::init_from_env("RUSTC_LOG");
}

pub fn main() {
pub fn main() -> ! {
let start = Instant::now();
init_rustc_env_logger();
let mut callbacks = TimePassesCallbacks::default();
install_ice_hook();
let result = catch_fatal_errors(|| {
let exit_code = catch_with_exit_code(|| {
let args = env::args_os()
.enumerate()
.map(|(i, arg)| {
Expand All @@ -1246,13 +1256,8 @@ pub fn main() {
})
.collect::<Vec<_>>();
run_compiler(&args, &mut callbacks, None, None)
})
.and_then(|result| result);
let exit_code = match result {
Ok(_) => EXIT_SUCCESS,
Err(_) => EXIT_FAILURE,
};
});
// The extra `\t` is necessary to align this label with the others.
print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed());
process::exit(exit_code);
process::exit(exit_code)
}
4 changes: 2 additions & 2 deletions src/librustc_expand/parse/lexer/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ fn t1() {
assert_eq!(string_reader.next_token(), token::Whitespace);
// Read another token.
let tok3 = string_reader.next_token();
assert_eq!(string_reader.pos.clone(), BytePos(28));
assert_eq!(string_reader.pos(), BytePos(28));
let tok4 = Token::new(mk_ident("main"), Span::with_root_ctxt(BytePos(24), BytePos(28)));
assert_eq!(tok3.kind, tok4.kind);
assert_eq!(tok3.span, tok4.span);

assert_eq!(string_reader.next_token(), token::OpenDelim(token::Paren));
assert_eq!(string_reader.pos.clone(), BytePos(29))
assert_eq!(string_reader.pos(), BytePos(29))
})
}

Expand Down
6 changes: 1 addition & 5 deletions src/librustc_middle/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,7 @@ impl<'hir> Map<'hir> {
/// Given a `HirId`, returns the `BodyId` associated with it,
/// if the node is a body owner, otherwise returns `None`.
pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> {
if let Some(node) = self.find(hir_id) {
associated_body(node)
} else {
bug!("no entry for id `{}`", hir_id)
}
self.find(hir_id).map(associated_body).flatten()
}

/// Given a body owner's id, returns the `BodyId` associated with it.
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_middle/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,12 @@ rustc_queries! {
desc { "evaluating trait selection obligation `{}`", goal.value }
}

query type_implements_trait(
key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
) -> bool {
desc { "evaluating `type_implements_trait` `{:?}`", key }
}

/// Do not call this query directly: part of the `Eq` type-op
query type_op_ascribe_user_type(
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_middle/ty/query/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,15 @@ impl Key for (Symbol, u32, u32) {
DUMMY_SP
}
}

impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
type CacheSelector = DefaultCacheSelector;

fn query_crate(&self) -> CrateNum {
LOCAL_CRATE
}

fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
7 changes: 7 additions & 0 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
value: OpTy<'tcx>,
source_info: SourceInfo,
) {
if let Rvalue::Use(Operand::Constant(c)) = rval {
if !matches!(c.literal.val, ConstKind::Unevaluated(..)) {
trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
return;
}
}

trace!("attepting to replace {:?} with {:?}", rval, value);
if let Err(e) = self.ecx.const_validate_operand(
value,
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_parse/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ pub struct StringReader<'a> {
/// Initial position, read-only.
start_pos: BytePos,
/// The absolute offset within the source_map of the current character.
// FIXME(#64197): `pub` is needed by tests for now.
pub pos: BytePos,
pos: BytePos,
/// Stop reading src at this index.
end_src_index: usize,
/// Source text to tokenize.
Expand Down Expand Up @@ -436,6 +435,10 @@ impl<'a> StringReader<'a> {
}
}

pub fn pos(&self) -> BytePos {
self.pos
}

#[inline]
fn src_index(&self, pos: BytePos) -> usize {
(pos - self.start_pos).to_usize()
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trait_selection/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
self.note_version_mismatch(&mut err, &trait_ref);
self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span);
if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
err.emit();
return;
Expand Down
101 changes: 101 additions & 0 deletions src/librustc_trait_selection/traits/error_reporting/suggestions.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use super::{
EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
SelectionContext,
};

use crate::infer::InferCtxt;
use crate::traits::normalize_projection_type;

use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
use rustc_middle::ty::TypeckTables;
use rustc_middle::ty::{
Expand Down Expand Up @@ -150,6 +153,15 @@ pub trait InferCtxtExt<'tcx> {
T: fmt::Display;

fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>);

/// Suggest to await before try: future? => future.await?
fn suggest_await_before_try(
&self,
err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
span: Span,
);
}

fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
Expand Down Expand Up @@ -1822,6 +1834,95 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
suggested_limit, self.tcx.crate_name,
));
}

fn suggest_await_before_try(
&self,
err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>,
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
span: Span,
) {
debug!(
"suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}",
obligation,
span,
trait_ref,
trait_ref.self_ty()
);
let body_hir_id = obligation.cause.body_id;
let item_id = self.tcx.hir().get_parent_node(body_hir_id);

if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) {
let body = self.tcx.hir().body(body_id);
if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
let future_trait =
self.tcx.require_lang_item(lang_items::FutureTraitLangItem, None);

let self_ty = self.resolve_vars_if_possible(&trait_ref.self_ty());

let impls_future = self.tcx.type_implements_trait((
future_trait,
self_ty,
ty::List::empty(),
obligation.param_env,
));

let item_def_id = self
.tcx
.associated_items(future_trait)
.in_definition_order()
.next()
.unwrap()
.def_id;
// `<T as Future>::Output`
let projection_ty = ty::ProjectionTy {
// `T`
substs: self.tcx.mk_substs_trait(
trait_ref.self_ty(),
self.fresh_substs_for_item(span, item_def_id),
),
// `Future::Output`
item_def_id,
};

let mut selcx = SelectionContext::new(self);

let mut obligations = vec![];
let normalized_ty = normalize_projection_type(
&mut selcx,
obligation.param_env,
projection_ty,
obligation.cause.clone(),
0,
&mut obligations,
);

debug!(
"suggest_await_befor_try: normalized_projection_type {:?}",
self.resolve_vars_if_possible(&normalized_ty)
);
let try_obligation = self.mk_obligation_for_def_id(
trait_ref.def_id(),
normalized_ty,
obligation.cause.clone(),
obligation.param_env,
);
debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation);
if self.predicate_may_hold(&try_obligation) && impls_future {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
if snippet.ends_with('?') {
err.span_suggestion(
span,
"consider using `.await` here",
format!("{}.await?", snippet.trim_end_matches('?')),
Applicability::MaybeIncorrect,
);
}
}
}
}
}
}
}

/// Collect all the returned expressions within the input expression.
Expand Down
42 changes: 41 additions & 1 deletion src/librustc_trait_selection/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ use rustc_hir::def_id::DefId;
use rustc_middle::middle::region;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_middle::ty::{
self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, WithConstness,
};
use rustc_span::Span;

use std::fmt::Debug;
Expand Down Expand Up @@ -523,6 +525,43 @@ fn vtable_methods<'tcx>(
}))
}

/// Check whether a `ty` implements given trait(trait_def_id).
///
/// NOTE: Always return `false` for a type which needs inference.
fn type_implements_trait<'tcx>(
tcx: TyCtxt<'tcx>,
key: (
DefId, // trait_def_id,
Ty<'tcx>, // type
SubstsRef<'tcx>,
ParamEnv<'tcx>,
),
) -> bool {
let (trait_def_id, ty, params, param_env) = key;

debug!(
"type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
trait_def_id, ty, params, param_env
);

// Do not check on infer_types to avoid panic in evaluate_obligation.
if ty.has_infer_types() {
return false;
}

let ty = tcx.erase_regions(&ty);

let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };

let obligation = Obligation {
cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: trait_ref.without_const().to_predicate(),
};
tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
}

pub fn provide(providers: &mut ty::query::Providers<'_>) {
object_safety::provide(providers);
*providers = ty::query::Providers {
Expand All @@ -531,6 +570,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
vtable_methods,
substitute_normalize_and_test_predicates,
type_implements_trait,
..*providers
};
}
Loading

0 comments on commit 163445a

Please sign in to comment.