[cfe] Support current uri for crashes during top level inference

+ avoid printing the stack trace twice on crash

Change-Id: Iac220117b77c30bc03212b2727efe88036819357
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260700
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
This commit is contained in:
Johnni Winther 2022-09-23 08:32:49 +00:00 committed by Commit Bot
parent 51114fca8a
commit d43aa20afa
8 changed files with 105 additions and 68 deletions

View file

@ -10,6 +10,7 @@ import 'dart:io'
show ContentType, HttpClient, HttpClientRequest, SocketException, stderr;
import 'problems.dart' show DebugAbort;
import 'uri_offset.dart';
const String defaultServerAddress = "http://127.0.0.1:59410/";
@ -35,11 +36,20 @@ class Crash {
@override
String toString() {
return """
Crash when compiling $uri,
at character offset $charOffset:
$error${trace == null ? '' : '\n$trace'}
""";
StringBuffer sb = new StringBuffer();
if (uri != null) {
sb.write("Crash when compiling $uri");
if (charOffset != null && charOffset != -1) {
sb.write(" at character offset $charOffset:\n");
} else {
sb.write(":\n");
}
} else {
sb.write("Crash when compiling:\n");
}
sb.write(error);
sb.write("\n");
return sb.toString();
}
}
@ -116,7 +126,7 @@ String safeToString(Object object) {
}
Future<T> withCrashReporting<T>(
Future<T> Function() action, Uri? Function() currentUri) async {
Future<T> Function() action, UriOffset? Function() currentUriOffset) async {
resetCrashReporting();
try {
return await action();
@ -125,6 +135,7 @@ Future<T> withCrashReporting<T>(
} on DebugAbort {
rethrow;
} catch (e, s) {
return reportCrash(e, s, currentUri());
UriOffset? uriOffset = currentUriOffset();
return reportCrash(e, s, uriOffset?.uri, uriOffset?.fileOffset);
}
}

View file

@ -315,29 +315,31 @@ class DeclaredSourceConstructorBuilder extends SourceFunctionBuilderImpl
void inferFormalTypes(ClassHierarchyBase hierarchy) {
if (_hasFormalsInferred) return;
if (formals != null) {
for (FormalParameterBuilder formal in formals!) {
if (formal.type is InferableTypeBuilder) {
if (formal.isInitializingFormal) {
formal.finalizeInitializingFormal(classBuilder, hierarchy);
libraryBuilder.loader.withUriForCrashReporting(fileUri, charOffset, () {
for (FormalParameterBuilder formal in formals!) {
if (formal.type is InferableTypeBuilder) {
if (formal.isInitializingFormal) {
formal.finalizeInitializingFormal(classBuilder, hierarchy);
}
}
}
}
if (_hasSuperInitializingFormals) {
List<Initializer>? initializers;
if (beginInitializers != null) {
BodyBuilder bodyBuilder = libraryBuilder.loader
.createBodyBuilderForOutlineExpression(libraryBuilder,
classBuilder, this, classBuilder.scope, fileUri);
if (isConst) {
bodyBuilder.constantContext = ConstantContext.required;
if (_hasSuperInitializingFormals) {
List<Initializer>? initializers;
if (beginInitializers != null) {
BodyBuilder bodyBuilder = libraryBuilder.loader
.createBodyBuilderForOutlineExpression(libraryBuilder,
classBuilder, this, classBuilder.scope, fileUri);
if (isConst) {
bodyBuilder.constantContext = ConstantContext.required;
}
initializers = bodyBuilder.parseInitializers(beginInitializers!,
doFinishConstructor: false);
}
initializers = bodyBuilder.parseInitializers(beginInitializers!,
doFinishConstructor: false);
finalizeSuperInitializingFormals(
hierarchy, _superParameterDefaultValueCloners, initializers);
}
finalizeSuperInitializingFormals(
hierarchy, _superParameterDefaultValueCloners, initializers);
}
});
}
_hasFormalsInferred = true;
}

View file

@ -481,35 +481,38 @@ class SourceFieldBuilder extends SourceMemberBuilderImpl
return fieldType;
}
InferredType implicitFieldType = fieldType as InferredType;
DartType inferredType = implicitFieldType.computeType(hierarchy);
if (fieldType is InferredType) {
// `fieldType` may have changed if a circularity was detected when
// [inferredType] was computed.
if (!libraryBuilder.isNonNullableByDefault) {
inferredType = legacyErasure(inferredType);
}
type.registerInferredType(inferredType);
return libraryBuilder.loader.withUriForCrashReporting(fileUri, charOffset,
() {
InferredType implicitFieldType = fieldType as InferredType;
DartType inferredType = implicitFieldType.computeType(hierarchy);
if (fieldType is InferredType) {
// `fieldType` may have changed if a circularity was detected when
// [inferredType] was computed.
if (!libraryBuilder.isNonNullableByDefault) {
inferredType = legacyErasure(inferredType);
}
type.registerInferredType(inferredType);
IncludesTypeParametersNonCovariantly? needsCheckVisitor;
if (parent is ClassBuilder) {
Class enclosingClass = classBuilder!.cls;
if (enclosingClass.typeParameters.isNotEmpty) {
needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
enclosingClass.typeParameters,
// We are checking the field type as if it is the type of the
// parameter of the implicit setter and this is a contravariant
// position.
initialVariance: Variance.contravariant);
IncludesTypeParametersNonCovariantly? needsCheckVisitor;
if (parent is ClassBuilder) {
Class enclosingClass = classBuilder!.cls;
if (enclosingClass.typeParameters.isNotEmpty) {
needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
enclosingClass.typeParameters,
// We are checking the field type as if it is the type of the
// parameter of the implicit setter and this is a contravariant
// position.
initialVariance: Variance.contravariant);
}
}
if (needsCheckVisitor != null) {
if (fieldType.accept(needsCheckVisitor)) {
_fieldEncoding.setGenericCovariantImpl();
}
}
}
if (needsCheckVisitor != null) {
if (fieldType.accept(needsCheckVisitor)) {
_fieldEncoding.setGenericCovariantImpl();
}
}
}
return fieldType;
return fieldType;
});
}
@override

View file

@ -86,6 +86,7 @@ import '../scope.dart';
import '../ticker.dart' show Ticker;
import '../type_inference/type_inference_engine.dart';
import '../type_inference/type_inferrer.dart';
import '../uri_offset.dart';
import '../util/helpers.dart';
import '../uris.dart';
import 'diet_listener.dart' show DietListener;
@ -229,7 +230,7 @@ class SourceLoader extends Loader {
int byteCount = 0;
Uri? currentUriForCrashReporting;
UriOffset? currentUriForCrashReporting;
ClassBuilder? _macroClassBuilder;
@ -287,6 +288,16 @@ class SourceLoader extends Loader {
_builders.clear();
}
/// Run [f] with [uri] and [fileOffset] as the current uri/offset used for
/// reporting crashes.
T withUriForCrashReporting<T>(Uri uri, int fileOffset, T Function() f) {
UriOffset? oldUriForCrashReporting = currentUriForCrashReporting;
currentUriForCrashReporting = new UriOffset(uri, fileOffset);
T result = f();
currentUriForCrashReporting = oldUriForCrashReporting;
return result;
}
@override
LibraryBuilder get coreLibrary => _coreLibrary!;
@ -659,7 +670,8 @@ class SourceLoader extends Loader {
Future<Null> buildBodies(List<SourceLibraryBuilder> libraryBuilders) async {
assert(_coreLibrary != null);
for (SourceLibraryBuilder library in libraryBuilders) {
currentUriForCrashReporting = library.importUri;
currentUriForCrashReporting =
new UriOffset(library.importUri, TreeNode.noOffset);
await buildBody(library);
}
// Workaround: This will return right away but avoid a "semi leak"
@ -1006,7 +1018,8 @@ severity: $severity
_ensureCoreLibrary();
while (_unparsedLibraries.isNotEmpty) {
SourceLibraryBuilder library = _unparsedLibraries.removeFirst();
currentUriForCrashReporting = library.importUri;
currentUriForCrashReporting =
new UriOffset(library.importUri, TreeNode.noOffset);
await buildOutline(library);
}
currentUriForCrashReporting = null;

View file

@ -35,6 +35,7 @@ import '../kernel/late_lowering.dart' as late_lowering;
import '../names.dart';
import '../problems.dart' show unhandled;
import '../source/source_library_builder.dart';
import '../uri_offset.dart';
import 'closure_context.dart';
import 'for_in.dart';
import 'inference_helper.dart';
@ -233,7 +234,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
/// Computes uri and offset for [node] for internal errors in a way that is
/// safe for both top-level and full inference.
_UriOffset _computeUriOffset(TreeNode node) {
UriOffset _computeUriOffset(TreeNode node) {
Uri uri;
int fileOffset;
if (!isTopLevel) {
@ -252,12 +253,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
fileOffset = TreeNode.noOffset;
}
}
return new _UriOffset(uri, fileOffset);
return new UriOffset(uri, fileOffset);
}
ExpressionInferenceResult _unhandledExpression(
Expression node, DartType typeContext) {
_UriOffset uriOffset = _computeUriOffset(node);
UriOffset uriOffset = _computeUriOffset(node);
unhandled("${node.runtimeType}", "InferenceVisitor", uriOffset.fileOffset,
uriOffset.uri);
}
@ -479,7 +480,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
}
StatementInferenceResult _unhandledStatement(Statement node) {
_UriOffset uriOffset = _computeUriOffset(node);
UriOffset uriOffset = _computeUriOffset(node);
return unhandled("${node.runtimeType}", "InferenceVisitor",
uriOffset.fileOffset, uriOffset.uri);
}
@ -1364,7 +1365,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
} else if (syntheticAssignment is InvalidExpression || hasProblem) {
return new InvalidForInVariable(syntheticAssignment);
} else {
_UriOffset uriOffset = _computeUriOffset(syntheticAssignment!);
UriOffset uriOffset = _computeUriOffset(syntheticAssignment!);
return unhandled(
"${syntheticAssignment.runtimeType}",
"handleForInStatementWithoutVariable",
@ -7455,13 +7456,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase
}
}
class _UriOffset {
final Uri uri;
final int fileOffset;
_UriOffset(this.uri, this.fileOffset);
}
/// Offset and type information collection in [InferenceVisitor.inferMapEntry].
class _MapLiteralEntryOffsets {
// Stores the offset of the map entry found by inferMapEntry.

View file

@ -0,0 +1,10 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class UriOffset {
final Uri uri;
final int fileOffset;
UriOffset(this.uri, this.fileOffset);
}

View file

@ -32,6 +32,7 @@ import 'fasta/kernel/macro/macro.dart';
import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
import 'fasta/kernel/verifier.dart' show verifyComponent;
import 'fasta/source/source_loader.dart' show SourceLoader;
import 'fasta/uri_offset.dart';
import 'fasta/uri_translator.dart' show UriTranslator;
/// Implementation for the
@ -120,7 +121,10 @@ Future<CompilerResult> generateKernelInternal(
includeHierarchyAndCoreTypes: includeHierarchyAndCoreTypes,
retainDataForTesting: retainDataForTesting);
}
}, () => sourceLoader?.currentUriForCrashReporting ?? options.inputs.first);
},
() =>
sourceLoader?.currentUriForCrashReporting ??
new UriOffset(options.inputs.first, TreeNode.noOffset));
}
Future<CompilerResult> _buildInternal(

View file

@ -312,7 +312,7 @@ class _AllFreeTypeVariablesVisitor implements DartTypeVisitor<void> {
@override
bool defaultDartType(DartType node) {
throw new UnsupportedError("Unsupported type $node (${node.runtimeType}.");
throw new UnsupportedError("Unsupported type $node (${node.runtimeType}).");
}
@override