Skip to content

Commit 163445a

Browse files
committed
Auto merge of rust-lang#72251 - Dylan-DPC:rollup-4mik3o7, r=Dylan-DPC
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
2 parents ed084b0 + a27b1b6 commit 163445a

File tree

37 files changed

+946
-210
lines changed

37 files changed

+946
-210
lines changed

src/libcore/num/mod.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1499,8 +1499,8 @@ any high-order bits of `rhs` that would cause the shift to exceed the bitwidth o
14991499
15001500
Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to
15011501
the range of the type, rather than the bits shifted out of the LHS being returned to the other end.
1502-
The primitive integer types all implement a `rotate_left` function, which may be what you want
1503-
instead.
1502+
The primitive integer types all implement a `[`rotate_left`](#method.rotate_left) function,
1503+
which may be what you want instead.
15041504
15051505
# Examples
15061506
@@ -1531,8 +1531,8 @@ removes any high-order bits of `rhs` that would cause the shift to exceed the bi
15311531
15321532
Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted
15331533
to the range of the type, rather than the bits shifted out of the LHS being returned to the other
1534-
end. The primitive integer types all implement a `rotate_right` function, which may be what you want
1535-
instead.
1534+
end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function,
1535+
which may be what you want instead.
15361536
15371537
# Examples
15381538
@@ -3610,8 +3610,8 @@ Note that this is *not* the same as a rotate-left; the
36103610
RHS of a wrapping shift-left is restricted to the range
36113611
of the type, rather than the bits shifted out of the LHS
36123612
being returned to the other end. The primitive integer
3613-
types all implement a `rotate_left` function, which may
3614-
be what you want instead.
3613+
types all implement a [`rotate_left`](#method.rotate_left) function,
3614+
which may be what you want instead.
36153615
36163616
# Examples
36173617
@@ -3644,8 +3644,8 @@ Note that this is *not* the same as a rotate-right; the
36443644
RHS of a wrapping shift-right is restricted to the range
36453645
of the type, rather than the bits shifted out of the LHS
36463646
being returned to the other end. The primitive integer
3647-
types all implement a `rotate_right` function, which may
3648-
be what you want instead.
3647+
types all implement a [`rotate_right`](#method.rotate_right) function,
3648+
which may be what you want instead.
36493649
36503650
# Examples
36513651

src/librustc_driver/lib.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,16 @@ pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorReported>
11381138
})
11391139
}
11401140

1141+
/// Variant of `catch_fatal_errors` for the `interface::Result` return type
1142+
/// that also computes the exit code.
1143+
pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
1144+
let result = catch_fatal_errors(f).and_then(|result| result);
1145+
match result {
1146+
Ok(()) => EXIT_SUCCESS,
1147+
Err(_) => EXIT_FAILURE,
1148+
}
1149+
}
1150+
11411151
lazy_static! {
11421152
static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static> = {
11431153
let hook = panic::take_hook();
@@ -1228,12 +1238,12 @@ pub fn init_rustc_env_logger() {
12281238
env_logger::init_from_env("RUSTC_LOG");
12291239
}
12301240

1231-
pub fn main() {
1241+
pub fn main() -> ! {
12321242
let start = Instant::now();
12331243
init_rustc_env_logger();
12341244
let mut callbacks = TimePassesCallbacks::default();
12351245
install_ice_hook();
1236-
let result = catch_fatal_errors(|| {
1246+
let exit_code = catch_with_exit_code(|| {
12371247
let args = env::args_os()
12381248
.enumerate()
12391249
.map(|(i, arg)| {
@@ -1246,13 +1256,8 @@ pub fn main() {
12461256
})
12471257
.collect::<Vec<_>>();
12481258
run_compiler(&args, &mut callbacks, None, None)
1249-
})
1250-
.and_then(|result| result);
1251-
let exit_code = match result {
1252-
Ok(_) => EXIT_SUCCESS,
1253-
Err(_) => EXIT_FAILURE,
1254-
};
1259+
});
12551260
// The extra `\t` is necessary to align this label with the others.
12561261
print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed());
1257-
process::exit(exit_code);
1262+
process::exit(exit_code)
12581263
}

src/librustc_expand/parse/lexer/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ fn t1() {
5050
assert_eq!(string_reader.next_token(), token::Whitespace);
5151
// Read another token.
5252
let tok3 = string_reader.next_token();
53-
assert_eq!(string_reader.pos.clone(), BytePos(28));
53+
assert_eq!(string_reader.pos(), BytePos(28));
5454
let tok4 = Token::new(mk_ident("main"), Span::with_root_ctxt(BytePos(24), BytePos(28)));
5555
assert_eq!(tok3.kind, tok4.kind);
5656
assert_eq!(tok3.span, tok4.span);
5757

5858
assert_eq!(string_reader.next_token(), token::OpenDelim(token::Paren));
59-
assert_eq!(string_reader.pos.clone(), BytePos(29))
59+
assert_eq!(string_reader.pos(), BytePos(29))
6060
})
6161
}
6262

src/librustc_middle/hir/map/mod.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,7 @@ impl<'hir> Map<'hir> {
390390
/// Given a `HirId`, returns the `BodyId` associated with it,
391391
/// if the node is a body owner, otherwise returns `None`.
392392
pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> {
393-
if let Some(node) = self.find(hir_id) {
394-
associated_body(node)
395-
} else {
396-
bug!("no entry for id `{}`", hir_id)
397-
}
393+
self.find(hir_id).map(associated_body).flatten()
398394
}
399395

400396
/// Given a body owner's id, returns the `BodyId` associated with it.

src/librustc_middle/query/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,12 @@ rustc_queries! {
11641164
desc { "evaluating trait selection obligation `{}`", goal.value }
11651165
}
11661166

1167+
query type_implements_trait(
1168+
key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
1169+
) -> bool {
1170+
desc { "evaluating `type_implements_trait` `{:?}`", key }
1171+
}
1172+
11671173
/// Do not call this query directly: part of the `Eq` type-op
11681174
query type_op_ascribe_user_type(
11691175
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>

src/librustc_middle/ty/query/keys.rs

+12
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,15 @@ impl Key for (Symbol, u32, u32) {
295295
DUMMY_SP
296296
}
297297
}
298+
299+
impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
300+
type CacheSelector = DefaultCacheSelector;
301+
302+
fn query_crate(&self) -> CrateNum {
303+
LOCAL_CRATE
304+
}
305+
306+
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
307+
DUMMY_SP
308+
}
309+
}

src/librustc_mir/transform/const_prop.rs

+7
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
616616
value: OpTy<'tcx>,
617617
source_info: SourceInfo,
618618
) {
619+
if let Rvalue::Use(Operand::Constant(c)) = rval {
620+
if !matches!(c.literal.val, ConstKind::Unevaluated(..)) {
621+
trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
622+
return;
623+
}
624+
}
625+
619626
trace!("attepting to replace {:?} with {:?}", rval, value);
620627
if let Err(e) = self.ecx.const_validate_operand(
621628
value,

src/librustc_parse/lexer/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ pub struct StringReader<'a> {
3131
/// Initial position, read-only.
3232
start_pos: BytePos,
3333
/// The absolute offset within the source_map of the current character.
34-
// FIXME(#64197): `pub` is needed by tests for now.
35-
pub pos: BytePos,
34+
pos: BytePos,
3635
/// Stop reading src at this index.
3736
end_src_index: usize,
3837
/// Source text to tokenize.
@@ -436,6 +435,10 @@ impl<'a> StringReader<'a> {
436435
}
437436
}
438437

438+
pub fn pos(&self) -> BytePos {
439+
self.pos
440+
}
441+
439442
#[inline]
440443
fn src_index(&self, pos: BytePos) -> usize {
441444
(pos - self.start_pos).to_usize()

src/librustc_trait_selection/traits/error_reporting/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
402402
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
403403
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
404404
self.note_version_mismatch(&mut err, &trait_ref);
405+
self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span);
405406
if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
406407
err.emit();
407408
return;

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

+101
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
use super::{
22
EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
3+
SelectionContext,
34
};
45

56
use crate::infer::InferCtxt;
7+
use crate::traits::normalize_projection_type;
68

79
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
810
use rustc_hir as hir;
911
use rustc_hir::def::DefKind;
1012
use rustc_hir::def_id::DefId;
1113
use rustc_hir::intravisit::Visitor;
14+
use rustc_hir::lang_items;
1215
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
1316
use rustc_middle::ty::TypeckTables;
1417
use rustc_middle::ty::{
@@ -150,6 +153,15 @@ pub trait InferCtxtExt<'tcx> {
150153
T: fmt::Display;
151154

152155
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>);
156+
157+
/// Suggest to await before try: future? => future.await?
158+
fn suggest_await_before_try(
159+
&self,
160+
err: &mut DiagnosticBuilder<'_>,
161+
obligation: &PredicateObligation<'tcx>,
162+
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
163+
span: Span,
164+
);
153165
}
154166

155167
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
@@ -1822,6 +1834,95 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
18221834
suggested_limit, self.tcx.crate_name,
18231835
));
18241836
}
1837+
1838+
fn suggest_await_before_try(
1839+
&self,
1840+
err: &mut DiagnosticBuilder<'_>,
1841+
obligation: &PredicateObligation<'tcx>,
1842+
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
1843+
span: Span,
1844+
) {
1845+
debug!(
1846+
"suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}",
1847+
obligation,
1848+
span,
1849+
trait_ref,
1850+
trait_ref.self_ty()
1851+
);
1852+
let body_hir_id = obligation.cause.body_id;
1853+
let item_id = self.tcx.hir().get_parent_node(body_hir_id);
1854+
1855+
if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) {
1856+
let body = self.tcx.hir().body(body_id);
1857+
if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
1858+
let future_trait =
1859+
self.tcx.require_lang_item(lang_items::FutureTraitLangItem, None);
1860+
1861+
let self_ty = self.resolve_vars_if_possible(&trait_ref.self_ty());
1862+
1863+
let impls_future = self.tcx.type_implements_trait((
1864+
future_trait,
1865+
self_ty,
1866+
ty::List::empty(),
1867+
obligation.param_env,
1868+
));
1869+
1870+
let item_def_id = self
1871+
.tcx
1872+
.associated_items(future_trait)
1873+
.in_definition_order()
1874+
.next()
1875+
.unwrap()
1876+
.def_id;
1877+
// `<T as Future>::Output`
1878+
let projection_ty = ty::ProjectionTy {
1879+
// `T`
1880+
substs: self.tcx.mk_substs_trait(
1881+
trait_ref.self_ty(),
1882+
self.fresh_substs_for_item(span, item_def_id),
1883+
),
1884+
// `Future::Output`
1885+
item_def_id,
1886+
};
1887+
1888+
let mut selcx = SelectionContext::new(self);
1889+
1890+
let mut obligations = vec![];
1891+
let normalized_ty = normalize_projection_type(
1892+
&mut selcx,
1893+
obligation.param_env,
1894+
projection_ty,
1895+
obligation.cause.clone(),
1896+
0,
1897+
&mut obligations,
1898+
);
1899+
1900+
debug!(
1901+
"suggest_await_befor_try: normalized_projection_type {:?}",
1902+
self.resolve_vars_if_possible(&normalized_ty)
1903+
);
1904+
let try_obligation = self.mk_obligation_for_def_id(
1905+
trait_ref.def_id(),
1906+
normalized_ty,
1907+
obligation.cause.clone(),
1908+
obligation.param_env,
1909+
);
1910+
debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation);
1911+
if self.predicate_may_hold(&try_obligation) && impls_future {
1912+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1913+
if snippet.ends_with('?') {
1914+
err.span_suggestion(
1915+
span,
1916+
"consider using `.await` here",
1917+
format!("{}.await?", snippet.trim_end_matches('?')),
1918+
Applicability::MaybeIncorrect,
1919+
);
1920+
}
1921+
}
1922+
}
1923+
}
1924+
}
1925+
}
18251926
}
18261927

18271928
/// Collect all the returned expressions within the input expression.

src/librustc_trait_selection/traits/mod.rs

+41-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ use rustc_hir::def_id::DefId;
3131
use rustc_middle::middle::region;
3232
use rustc_middle::ty::fold::TypeFoldable;
3333
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
34-
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness};
34+
use rustc_middle::ty::{
35+
self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, WithConstness,
36+
};
3537
use rustc_span::Span;
3638

3739
use std::fmt::Debug;
@@ -523,6 +525,43 @@ fn vtable_methods<'tcx>(
523525
}))
524526
}
525527

528+
/// Check whether a `ty` implements given trait(trait_def_id).
529+
///
530+
/// NOTE: Always return `false` for a type which needs inference.
531+
fn type_implements_trait<'tcx>(
532+
tcx: TyCtxt<'tcx>,
533+
key: (
534+
DefId, // trait_def_id,
535+
Ty<'tcx>, // type
536+
SubstsRef<'tcx>,
537+
ParamEnv<'tcx>,
538+
),
539+
) -> bool {
540+
let (trait_def_id, ty, params, param_env) = key;
541+
542+
debug!(
543+
"type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
544+
trait_def_id, ty, params, param_env
545+
);
546+
547+
// Do not check on infer_types to avoid panic in evaluate_obligation.
548+
if ty.has_infer_types() {
549+
return false;
550+
}
551+
552+
let ty = tcx.erase_regions(&ty);
553+
554+
let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };
555+
556+
let obligation = Obligation {
557+
cause: ObligationCause::dummy(),
558+
param_env,
559+
recursion_depth: 0,
560+
predicate: trait_ref.without_const().to_predicate(),
561+
};
562+
tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
563+
}
564+
526565
pub fn provide(providers: &mut ty::query::Providers<'_>) {
527566
object_safety::provide(providers);
528567
*providers = ty::query::Providers {
@@ -531,6 +570,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
531570
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
532571
vtable_methods,
533572
substitute_normalize_and_test_predicates,
573+
type_implements_trait,
534574
..*providers
535575
};
536576
}

0 commit comments

Comments
 (0)