Skip to content

Commit

Permalink
Auto merge of #89882 - matthiaskrgr:rollup-1dh7pz8, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 6 pull requests

Successful merges:

 - #89390 (Fix incorrect Box::pin suggestion)
 - #89433 (Fix ctrl-c causing reads of stdin to return empty on Windows.)
 - #89823 (Switch order of terms to prevent overflow)
 - #89865 (Allow static linking LLVM with ThinLTO)
 - #89873 (Add missing word to `FromStr` trait documentation)
 - #89878 (Fix missing remaining compiler specific cfg information)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Oct 14, 2021
2 parents 0a56eb1 + d6eff5a commit e1e9319
Show file tree
Hide file tree
Showing 14 changed files with 120 additions and 49 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/project.rs
Expand Up @@ -558,7 +558,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
let infcx = self.infcx;
let index =
self.universe_indices.len() - debruijn.as_usize() + self.current_index.as_usize() - 1;
self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
let universe = self.universe_indices[index].unwrap_or_else(|| {
for i in self.universe_indices.iter_mut().take(index + 1) {
*i = i.or_else(|| Some(infcx.create_next_universe()))
Expand Down
18 changes: 15 additions & 3 deletions compiler/rustc_typeck/src/check/coercion.rs
Expand Up @@ -42,7 +42,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{Coercion, InferOk, InferResult};
use rustc_infer::traits::Obligation;
use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
Expand Down Expand Up @@ -146,6 +146,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
.and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations))
}

#[instrument(skip(self))]
fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
// First, remove any resolved type variables (at the top level, at least):
let a = self.shallow_resolve(a);
Expand Down Expand Up @@ -933,14 +934,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

/// Same as `try_coerce()`, but without side-effects.
///
/// Returns false if the coercion creates any obligations that result in
/// errors.
pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
let source = self.resolve_vars_with_obligations(expr_ty);
debug!("coercion::can({:?} -> {:?})", source, target);
debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);

let cause = self.cause(rustc_span::DUMMY_SP, ObligationCauseCode::ExprAssignable);
// We don't ever need two-phase here since we throw out the result of the coercion
let coerce = Coerce::new(self, cause, AllowTwoPhase::No);
self.probe(|_| coerce.coerce(source, target)).is_ok()
self.probe(|_| {
let ok = match coerce.coerce(source, target) {
Ok(ok) => ok,
_ => return false,
};
let mut fcx = traits::FulfillmentContext::new_in_snapshot();
fcx.register_predicate_obligations(self, ok.obligations);
fcx.select_where_possible(&self).is_ok()
})
}

/// Given a type and a target type, this function will calculate and return
Expand Down
33 changes: 24 additions & 9 deletions compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
Expand Up @@ -341,7 +341,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (sp, label) in spans_and_labels {
multi_span.push_span_label(sp, label);
}
err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables");
err.span_note(
multi_span,
"closures can only be coerced to `fn` types if they do not capture any variables"
);
}
}
}
Expand All @@ -361,15 +364,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
let pin_did = self.tcx.lang_items().pin_type();
// This guards the `unwrap` and `mk_box` below.
if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() {
return false;
}
match expected.kind() {
ty::Adt(def, _) if Some(def.did) != pin_did => return false,
// This guards the `unwrap` and `mk_box` below.
_ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return false,
_ => {}
ty::Adt(def, _) if Some(def.did) == pin_did => (),
_ => return false,
}
let boxed_found = self.tcx.mk_box(found);
let new_found = self.tcx.mk_lang_item(boxed_found, LangItem::Pin).unwrap();
if self.can_coerce(new_found, expected) {
let box_found = self.tcx.mk_box(found);
let pin_box_found = self.tcx.mk_lang_item(box_found, LangItem::Pin).unwrap();
let pin_found = self.tcx.mk_lang_item(found, LangItem::Pin).unwrap();
if self.can_coerce(pin_box_found, expected) {
debug!("can coerce {:?} to {:?}, suggesting Box::pin", pin_box_found, expected);
match found.kind() {
ty::Adt(def, _) if def.is_box() => {
err.help("use `Box::pin`");
Expand All @@ -381,11 +388,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(expr.span.shrink_to_lo(), "Box::pin(".to_string()),
(expr.span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
Applicability::MaybeIncorrect,
);
}
}
true
} else if self.can_coerce(pin_found, expected) {
match found.kind() {
ty::Adt(def, _) if def.is_box() => {
err.help("use `Box::pin`");
true
}
_ => false,
}
} else {
false
}
Expand Down
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Expand Up @@ -74,6 +74,7 @@
not(any(test, bootstrap)),
any(not(feature = "miri-test-libstd"), test, doctest),
no_global_oom_handling,
not(no_global_oom_handling),
target_has_atomic = "ptr"
))
)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/str/traits.rs
Expand Up @@ -536,7 +536,7 @@ pub trait FromStr: Sized {
///
/// If parsing succeeds, return the value inside [`Ok`], otherwise
/// when the string is ill-formatted return an error specific to the
/// inside [`Err`]. The error type is specific to implementation of the trait.
/// inside [`Err`]. The error type is specific to the implementation of the trait.
///
/// # Examples
///
Expand Down
10 changes: 9 additions & 1 deletion library/std/src/lib.rs
Expand Up @@ -195,7 +195,15 @@
test(no_crate_inject, attr(deny(warnings))),
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]
#![cfg_attr(not(bootstrap), doc(cfg_hide(not(test), not(any(test, bootstrap)))))]
#![cfg_attr(
not(bootstrap),
doc(cfg_hide(
not(test),
not(any(test, bootstrap)),
no_global_oom_handling,
not(no_global_oom_handling)
))
)]
// Don't link to std. We are std.
#![no_std]
#![warn(deprecated_in_future)]
Expand Down
28 changes: 19 additions & 9 deletions library/std/src/sys/windows/stdio.rs
Expand Up @@ -291,15 +291,25 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result<usize> {
};

let mut amount = 0;
cvt(unsafe {
c::ReadConsoleW(
handle,
buf.as_mut_ptr() as c::LPVOID,
buf.len() as u32,
&mut amount,
&mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
)
})?;
loop {
cvt(unsafe {
c::SetLastError(0);
c::ReadConsoleW(
handle,
buf.as_mut_ptr() as c::LPVOID,
buf.len() as u32,
&mut amount,
&mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
)
})?;

// ReadConsoleW returns success with ERROR_OPERATION_ABORTED for Ctrl-C or Ctrl-Break.
// Explicitly check for that case here and try again.
if amount == 0 && unsafe { c::GetLastError() } == c::ERROR_OPERATION_ABORTED {
continue;
}
break;
}

if amount > 0 && buf[amount as usize - 1] == CTRL_Z {
amount -= 1;
Expand Down
13 changes: 4 additions & 9 deletions src/bootstrap/config.rs
Expand Up @@ -825,15 +825,10 @@ impl Config {
};
}

if config.llvm_thin_lto {
// If we're building with ThinLTO on, we want to link to LLVM
// shared, to avoid re-doing ThinLTO (which happens in the link
// step) with each stage.
assert_ne!(
llvm.link_shared,
Some(false),
"setting link-shared=false is incompatible with thin-lto=true"
);
if config.llvm_thin_lto && llvm.link_shared.is_none() {
// If we're building with ThinLTO on, by default we want to link
// to LLVM shared, to avoid re-doing ThinLTO (which happens in
// the link step) with each stage.
config.llvm_link_shared = true;
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/cross/cross-borrow-trait.stderr
Expand Up @@ -2,10 +2,8 @@ error[E0308]: mismatched types
--> $DIR/cross-borrow-trait.rs:10:26
|
LL | let _y: &dyn Trait = x;
| ---------- ^
| | |
| | expected `&dyn Trait`, found struct `Box`
| | help: consider borrowing here: `&x`
| ---------- ^ expected `&dyn Trait`, found struct `Box`
| |
| expected due to this
|
= note: expected reference `&dyn Trait`
Expand Down
12 changes: 4 additions & 8 deletions src/test/ui/dst/dst-bad-coercions.stderr
Expand Up @@ -13,10 +13,8 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-coercions.rs:15:21
|
LL | let y: &dyn T = x;
| ------ ^
| | |
| | expected `&dyn T`, found *-ptr
| | help: consider borrowing here: `&x`
| ------ ^ expected `&dyn T`, found *-ptr
| |
| expected due to this
|
= note: expected reference `&dyn T`
Expand All @@ -37,10 +35,8 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-coercions.rs:20:21
|
LL | let y: &dyn T = x;
| ------ ^
| | |
| | expected `&dyn T`, found *-ptr
| | help: consider borrowing here: `&x`
| ------ ^ expected `&dyn T`, found *-ptr
| |
| expected due to this
|
= note: expected reference `&dyn T`
Expand Down
22 changes: 22 additions & 0 deletions src/test/ui/suggestions/box-future-wrong-output.rs
@@ -0,0 +1,22 @@
// Issue #72117
// edition:2018

use core::future::Future;
use core::pin::Pin;

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

impl<T: ?Sized> FutureExt for T where T: Future {}
trait FutureExt: Future {
fn boxed<'a>(self) -> BoxFuture<'a, Self::Output>
where
Self: Sized + Send + 'a,
{
Box::pin(self)
}
}

fn main() {
let _: BoxFuture<'static, bool> = async {}.boxed();
//~^ ERROR: mismatched types
}
14 changes: 14 additions & 0 deletions src/test/ui/suggestions/box-future-wrong-output.stderr
@@ -0,0 +1,14 @@
error[E0308]: mismatched types
--> $DIR/box-future-wrong-output.rs:20:39
|
LL | let _: BoxFuture<'static, bool> = async {}.boxed();
| ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()`
| |
| expected due to this
|
= note: expected struct `Pin<Box<(dyn Future<Output = bool> + Send + 'static)>>`
found struct `Pin<Box<dyn Future<Output = ()> + Send>>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
6 changes: 3 additions & 3 deletions src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs
Expand Up @@ -11,13 +11,13 @@ fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32>
x //~ ERROR mismatched types
}

// This case is still subpar:
// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)`
// Should suggest changing the code from `Pin::new` to `Box::pin`.
fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
Box::new(x) //~ ERROR mismatched types
}

// This case is still subpar:
// `Pin::new(x)`: store this in the heap by calling `Box::new`: `Box::new(x)`
// Should suggest changing the code from `Pin::new` to `Box::pin`.
fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
Pin::new(x) //~ ERROR mismatched types
//~^ ERROR E0277
Expand Down
Expand Up @@ -15,7 +15,7 @@ LL | Box::pin(x)
| +++++++++ +

error[E0308]: mismatched types
--> $DIR/expected-boxed-future-isnt-pinned.rs:18:5
--> $DIR/expected-boxed-future-isnt-pinned.rs:15:5
|
LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
Expand Down

0 comments on commit e1e9319

Please sign in to comment.