Rework rmake support library API
### Take 1: Strongly-typed API
Context: https://github.com/rust-lang/rust/pull/122448#discussion_r1523774427
> My 2 cents: from my experience with writing similar "test DSLs", I would suggest to create these helpers as soon as possible in the process (basically the first time someone needs them, not only after N similar usages), and basically treat any imperative code in these high-level tests as a maintenance burden, basically making them as declarative as possible. Otherwise it might be a bit annoying to keep refactoring the tests later once such helpers are available.
>
> I would even discourage the arg method and create explicit methods for setting things like unpretty, the output file etc., but this might be more controversial, as it will make the invoked command-line arguments more opaque.
cc `@Kobzol` for the testing DSL suggestion.
Example:
```rs
let output = Rustc::new()
.input_file("main.rs")
.emit(&[EmitKind::Metadata])
.extern_("stable", &stable_path)
.output();
```
### Take 2: xshell-based macro API
Example:
```rs
let sh = Shell::new()?;
let stable_path = stable_path.to_string_lossy();
let output = cmd!(sh, "rustc main.rs --emit=metadata --extern stable={stable_path}").output()?;
```
### Take 3: Weakly-typed API with a few helper methods
```rs
let output = Rustc::new()
.input("main.rs")
.emit("metadata")
.extern_("stable", &stable_path)
.output();
```
Stop doing expensive work in `opt_suggest_box_span` eagerly
This PR defers the `can_coerce` and `predicate_must_hold_modulo_regions` calls in `opt_suggest_box_span`, and instead defers it until error reporting. This requires pulling the logic out of `note_obligation_cause_code` and into coercion, where we have access to the trait solver.
This also allows us to remove `TypeVariableOriginKind::OpaqueTypeInference`.